Skip to content

Commit 91fc4ec

Browse files
committed
BAEL-2275: Init version
1 parent 148e421 commit 91fc4ec

25 files changed

Lines changed: 626 additions & 0 deletions

ddd/docker/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ORDER_DOCKER_MONGODB_PORT=27017

ddd/docker/docker-compose.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: '3'
2+
3+
services:
4+
order-mongo-database:
5+
image: mongo:3.4.13
6+
restart: always
7+
ports:
8+
- ${ORDER_DOCKER_MONGODB_PORT}:27017
9+
environment:
10+
MONGO_INITDB_ROOT_USERNAME: admin
11+
MONGO_INITDB_ROOT_PASSWORD: admin
12+
MONGO_INITDB_DATABASE: order-database
13+
volumes:
14+
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

ddd/docker/mongo-init.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
db.createUser(
2+
{
3+
user: "order",
4+
pwd: "order",
5+
roles: [
6+
{
7+
role: "readWrite",
8+
db: "order-database"
9+
}
10+
]
11+
}
12+
);

ddd/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@
7474
<artifactId>spring-boot-starter-test</artifactId>
7575
<scope>test</scope>
7676
</dependency>
77+
<dependency>
78+
<groupId>org.mockito</groupId>
79+
<artifactId>mockito-core</artifactId>
80+
<scope>test</scope>
81+
</dependency>
7782
<dependency>
7883
<groupId>de.flapdoodle.embed</groupId>
7984
<artifactId>de.flapdoodle.embed.mongo</artifactId>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.baeldung.ddd.layers;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.context.annotation.PropertySource;
6+
7+
@SpringBootApplication
8+
@PropertySource(value={"classpath:ddd-layers.properties"})
9+
public class DomainLayerApplication {
10+
public static void main(String[] args) {
11+
SpringApplication.run(DomainLayerApplication.class, args);
12+
}
13+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.baeldung.ddd.layers.application;
2+
3+
import com.baeldung.ddd.layers.application.request.AddProductRequest;
4+
import com.baeldung.ddd.layers.application.request.CreateOrderRequest;
5+
import com.baeldung.ddd.layers.application.response.CreateOrderResponse;
6+
import com.baeldung.ddd.layers.domain.service.OrderService;
7+
import org.bson.types.ObjectId;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.http.MediaType;
10+
import org.springframework.web.bind.annotation.*;
11+
12+
@RestController
13+
@RequestMapping("/orders")
14+
public class OrderController {
15+
16+
private final OrderService orderService;
17+
18+
@Autowired
19+
public OrderController(OrderService orderService) {
20+
this.orderService = orderService;
21+
}
22+
23+
@PostMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
24+
CreateOrderResponse createOrder(@RequestBody final CreateOrderRequest createOrderRequest) {
25+
return new CreateOrderResponse(orderService
26+
.createOrder(createOrderRequest.getProducts())
27+
.toString());
28+
}
29+
30+
@PostMapping(value = "/{id}/products", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
31+
void addProduct(@PathVariable final ObjectId id, @RequestBody final AddProductRequest addProductRequest) {
32+
orderService.addProduct(id, addProductRequest.getProduct());
33+
}
34+
35+
@DeleteMapping(value = "/{id}/products", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
36+
void deleteProduct(@PathVariable final ObjectId id, @RequestParam final String name) {
37+
orderService.deleteProduct(id, name);
38+
}
39+
40+
@PostMapping("/{id}/complete")
41+
void completeOrder(@PathVariable final ObjectId id) {
42+
orderService.completeOrder(id);
43+
}
44+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.baeldung.ddd.layers.application.request;
2+
3+
import com.baeldung.ddd.layers.domain.Product;
4+
import com.fasterxml.jackson.annotation.JsonCreator;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
public class AddProductRequest {
8+
private Product product;
9+
10+
@JsonCreator
11+
public AddProductRequest(@JsonProperty("product") final Product product) {
12+
this.product = product;
13+
}
14+
15+
public Product getProduct() {
16+
return product;
17+
}
18+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.baeldung.ddd.layers.application.request;
2+
3+
import com.baeldung.ddd.layers.domain.Product;
4+
import com.fasterxml.jackson.annotation.JsonCreator;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
public class CreateOrderRequest {
11+
private List<Product> products;
12+
13+
@JsonCreator
14+
public CreateOrderRequest(@JsonProperty("products") final List<Product> productList) {
15+
this.products = new ArrayList<>(productList);
16+
}
17+
18+
public List<Product> getProducts() {
19+
return products;
20+
}
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.baeldung.ddd.layers.application.response;
2+
3+
import org.bson.types.ObjectId;
4+
5+
public class CreateOrderResponse {
6+
private final String id;
7+
8+
public CreateOrderResponse(String id) {
9+
this.id = id;
10+
}
11+
12+
public String getId() {
13+
return id;
14+
}
15+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.baeldung.ddd.layers.domain;
2+
3+
import com.baeldung.ddd.layers.domain.exception.DomainException;
4+
import org.bson.types.ObjectId;
5+
6+
import java.math.BigDecimal;
7+
import java.util.ArrayList;
8+
import java.util.Collections;
9+
import java.util.List;
10+
11+
public class Order {
12+
private final ObjectId id;
13+
private OrderStatus status;
14+
private List<Product> products;
15+
private BigDecimal price;
16+
17+
public Order(final ObjectId id, final List<Product> products) {
18+
this.id = id;
19+
this.products = new ArrayList<>(products);
20+
this.status = OrderStatus.CREATED;
21+
this.price = products
22+
.stream()
23+
.map(Product::getPrice)
24+
.reduce(BigDecimal.ZERO, BigDecimal::add);
25+
}
26+
27+
public void complete() {
28+
validateState();
29+
this.status = OrderStatus.COMPLETED;
30+
}
31+
32+
public void addProduct(final Product product) {
33+
validateState();
34+
validateProduct(product);
35+
products.add(product);
36+
price = price.add(product.getPrice());
37+
}
38+
39+
public void removeProduct(final String name) {
40+
validateState();
41+
final Product product = getProduct(name);
42+
products.remove(product);
43+
44+
price = price.subtract(product.getPrice());
45+
}
46+
47+
private Product getProduct(String name) {
48+
return products
49+
.stream()
50+
.filter(product -> product
51+
.getName()
52+
.equals(name))
53+
.findFirst()
54+
.orElseThrow(() -> new DomainException("Product with " + name + " doesn't exist."));
55+
}
56+
57+
private void validateState() {
58+
if (OrderStatus.COMPLETED.equals(status)) {
59+
throw new DomainException("The order is in completed state.");
60+
}
61+
}
62+
63+
private void validateProduct(final Product product) {
64+
if (product == null) {
65+
throw new DomainException("The product cannot be null.");
66+
}
67+
}
68+
69+
public ObjectId getId() {
70+
return id;
71+
}
72+
73+
public OrderStatus getStatus() {
74+
return status;
75+
}
76+
77+
public List<Product> getProducts() {
78+
return Collections.unmodifiableList(products);
79+
}
80+
81+
public BigDecimal getPrice() {
82+
return price;
83+
}
84+
}

0 commit comments

Comments
 (0)