Skip to content

Commit edbb59a

Browse files
JabezBrewiluwatar
andauthored
refactor: Refactored Layers Architecture To Be A Spring Boot Application. Issue iluwatar#2450 (iluwatar#2469)
* iluwatar#2450 1. Refactored Layers Architecture to be a Spring boot app. 2. Changed the xml-based configuration to annotation-based. 3. Used spring's constructor injection to pass around needed objects. 4. Implemented deleteAll() methods for the CakeBakingServiceImpl to be used during testing 5. Implemented a CommandLineRunner to run the spring boot app. And others. * iluwatar#2450 added the contents of the etc directory and a README.md * iluwatar#2450 made corrections in response to the PR tests * iluwatar#2450 made corrections in response to requested changes * iluwatar#2450 made corrections in response to requested changes --------- Co-authored-by: Ilkka Seppälä <[email protected]>
1 parent e40923d commit edbb59a

34 files changed

+1022
-1198
lines changed

layers/README.md

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,43 @@ title: Layers
33
category: Architectural
44
language: en
55
tag:
6-
- Decoupling
6+
- Decoupling
77
---
88

99
## Intent
1010

11-
Layers is an architectural pattern where software responsibilities are divided among the different
11+
Layers is an architectural pattern where software responsibilities are divided among the different
1212
layers of the application.
1313

1414
## Explanation
1515

1616
Real world example
1717

18-
> Consider a web site displaying decorated cakes for weddings and such. Instead of the web page
19-
> directly reaching into the database, it relies on a service to deliver this information. The
18+
> Consider a website displaying decorated cakes for weddings and such. Instead of the web page
19+
> directly reaching into the database, it relies on a service to deliver this information. The
2020
> service then queries the data layer to assimilate the needed information.
21-
2221
In plain words
2322

24-
> With Layers architectural pattern different concerns reside on separate layers. View layer is
25-
> interested only in rendering, service layer assembles the requested data from various sources, and
23+
> With Layers architectural pattern different concerns reside on separate layers. View layer is
24+
> interested only in rendering, service layer assembles the requested data from various sources, and
2625
> data layer gets the bits from the data storage.
27-
2826
Wikipedia says
2927

30-
> In software engineering, multitier architecture (often referred to as n-tier architecture) or
31-
> multilayered architecture is a client–server architecture in which presentation, application
28+
> In software engineering, multitier architecture (often referred to as n-tier architecture) or
29+
> multilayered architecture is a client–server architecture in which presentation, application
3230
> processing, and data management functions are physically separated.
33-
3431
**Programmatic Example**
3532

3633
On the data layer, we keep our cake building blocks. `Cake` consist of layers and topping.
3734

3835
```java
3936
@Entity
4037
public class Cake {
41-
4238
@Id
4339
@GeneratedValue
4440
private Long id;
45-
4641
@OneToOne(cascade = CascadeType.REMOVE)
4742
private CakeTopping topping;
48-
4943
@OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)
5044
private Set<CakeLayer> layers;
5145
}
@@ -55,17 +49,11 @@ The service layer offers `CakeBakingService` for easy access to different aspect
5549

5650
```java
5751
public interface CakeBakingService {
58-
5952
void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;
60-
6153
List<CakeInfo> getAllCakes();
62-
6354
void saveNewTopping(CakeToppingInfo toppingInfo);
64-
6555
List<CakeToppingInfo> getAvailableToppings();
66-
6756
void saveNewLayer(CakeLayerInfo layerInfo);
68-
6957
List<CakeLayerInfo> getAvailableLayers();
7058
}
7159
```
@@ -74,20 +62,14 @@ On the top we have our `View` responsible of rendering the cakes.
7462

7563
```java
7664
public interface View {
77-
7865
void render();
79-
8066
}
81-
8267
@Slf4j
8368
public class CakeViewImpl implements View {
84-
8569
private final CakeBakingService cakeBakingService;
86-
8770
public CakeViewImpl(CakeBakingService cakeBakingService) {
8871
this.cakeBakingService = cakeBakingService;
8972
}
90-
9173
public void render() {
9274
cakeBakingService.getAllCakes().forEach(cake -> LOGGER.info(cake.toString()));
9375
}
@@ -108,4 +90,4 @@ Use the Layers architecture when
10890

10991
## Credits
11092

111-
* [Pattern Oriented Software Architecture Volume 1: A System of Patterns](https://www.amazon.com/gp/product/0471958697/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0471958697&linkCode=as2&tag=javadesignpat-20&linkId=e3f42d7a2a4cc8c619bbc0136b20dadb)
93+
* [Pattern Oriented Software Architecture Volume 1: A System of Patterns](https://www.amazon.com/gp/product/0471958697/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0471958697&linkCode=as2&tag=javadesignpat-20&linkId=e3f42d7a2a4cc8c619bbc0136b20dadb)

layers/etc/layers.ucls

Lines changed: 239 additions & 239 deletions
Large diffs are not rendered by default.

layers/etc/layers.urm.puml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,6 @@ CakeViewImpl --> "-cakeBakingService" CakeBakingService
131131
App --> "-cakeBakingService" CakeBakingService
132132
Cake --> "-topping" CakeTopping
133133
CakeLayer --> "-cake" Cake
134-
CakeBakingServiceImpl ..|> CakeBakingService
135-
CakeViewImpl ..|> View
134+
CakeBakingServiceImpl ..|> CakeBakingService
135+
CakeViewImpl ..|> View
136136
@enduml

layers/pom.xml

Lines changed: 57 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
3-
43
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5-
64
The MIT License
75
Copyright © 2014-2022 Ilkka Seppälä
8-
96
Permission is hereby granted, free of charge, to any person obtaining a copy
107
of this software and associated documentation files (the "Software"), to deal
118
in the Software without restriction, including without limitation the rights
@@ -22,67 +19,63 @@
2219
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2320
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2421
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25-
THE SOFTWARE.
22+
THE SOFTWARE.-->
2623

27-
-->
28-
<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">
29-
<modelVersion>4.0.0</modelVersion>
30-
<parent>
24+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
25+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
26+
<modelVersion>4.0.0</modelVersion>
27+
<parent>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-parent</artifactId>
30+
<version>3.0.2</version>
31+
<relativePath/> <!-- lookup parent from repository -->
32+
</parent>
3133
<groupId>com.iluwatar</groupId>
32-
<artifactId>java-design-patterns</artifactId>
33-
<version>1.26.0-SNAPSHOT</version>
34-
</parent>
35-
<groupId>com.iluwatar.layers</groupId>
36-
<artifactId>layers</artifactId>
37-
<dependencies>
38-
<dependency>
39-
<groupId>org.springframework.data</groupId>
40-
<artifactId>spring-data-jpa</artifactId>
41-
</dependency>
42-
<dependency>
43-
<groupId>org.hibernate</groupId>
44-
<artifactId>hibernate-core</artifactId>
45-
</dependency>
46-
<dependency>
47-
<groupId>javax.xml.bind</groupId>
48-
<artifactId>jaxb-api</artifactId>
49-
</dependency>
50-
<dependency>
51-
<groupId>commons-dbcp</groupId>
52-
<artifactId>commons-dbcp</artifactId>
53-
</dependency>
54-
<dependency>
55-
<groupId>com.h2database</groupId>
56-
<artifactId>h2</artifactId>
57-
</dependency>
58-
<dependency>
59-
<groupId>org.junit.jupiter</groupId>
60-
<artifactId>junit-jupiter-engine</artifactId>
61-
<scope>test</scope>
62-
</dependency>
63-
<dependency>
64-
<groupId>org.mockito</groupId>
65-
<artifactId>mockito-core</artifactId>
66-
<scope>test</scope>
67-
</dependency>
68-
</dependencies>
69-
<build>
70-
<plugins>
71-
<plugin>
72-
<groupId>org.apache.maven.plugins</groupId>
73-
<artifactId>maven-assembly-plugin</artifactId>
74-
<executions>
75-
<execution>
76-
<configuration>
77-
<archive>
78-
<manifest>
79-
<mainClass>com.iluwatar.layers.app.App</mainClass>
80-
</manifest>
81-
</archive>
82-
</configuration>
83-
</execution>
84-
</executions>
85-
</plugin>
86-
</plugins>
87-
</build>
34+
<artifactId>layers</artifactId>
35+
<name>layers</name>
36+
<description>layers</description>
37+
<dependencies>
38+
<dependency>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-starter</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.springframework.boot</groupId>
44+
<artifactId>spring-boot-starter-data-jpa</artifactId>
45+
</dependency>
46+
47+
<dependency>
48+
<groupId>com.h2database</groupId>
49+
<artifactId>h2</artifactId>
50+
<scope>runtime</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>org.projectlombok</groupId>
54+
<artifactId>lombok</artifactId>
55+
<optional>true</optional>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.springframework.boot</groupId>
59+
<artifactId>spring-boot-starter-test</artifactId>
60+
<scope>test</scope>
61+
</dependency>
62+
</dependencies>
63+
64+
<build>
65+
<plugins>
66+
<plugin>
67+
<groupId>org.springframework.boot</groupId>
68+
<artifactId>spring-boot-maven-plugin</artifactId>
69+
<configuration>
70+
<excludes>
71+
<exclude>
72+
<groupId>org.projectlombok</groupId>
73+
<artifactId>lombok</artifactId>
74+
</exclude>
75+
</excludes>
76+
</configuration>
77+
</plugin>
78+
</plugins>
79+
</build>
80+
8881
</project>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.iluwatar.layers;
2+
3+
import dto.CakeInfo;
4+
import dto.CakeLayerInfo;
5+
import dto.CakeToppingInfo;
6+
import exception.CakeBakingException;
7+
import lombok.extern.slf4j.Slf4j;
8+
import service.CakeBakingService;
9+
import view.CakeViewImpl;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.boot.CommandLineRunner;
12+
import org.springframework.stereotype.Component;
13+
14+
import java.util.List;
15+
16+
@Component
17+
@Slf4j
18+
public class Runner implements CommandLineRunner {
19+
private final CakeBakingService cakeBakingService;
20+
public static final String STRAWBERRY = "strawberry";
21+
22+
@Autowired
23+
public Runner(CakeBakingService cakeBakingService) {
24+
this.cakeBakingService = cakeBakingService;
25+
}
26+
@Override
27+
public void run(String... args) {
28+
//initialize sample data
29+
initializeData();
30+
// create view and render it
31+
var cakeView = new CakeViewImpl(cakeBakingService);
32+
cakeView.render();
33+
}
34+
35+
/**
36+
* Initializes the example data.
37+
*/
38+
private void initializeData() {
39+
cakeBakingService.saveNewLayer(new CakeLayerInfo("chocolate", 1200));
40+
cakeBakingService.saveNewLayer(new CakeLayerInfo("banana", 900));
41+
cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));
42+
cakeBakingService.saveNewLayer(new CakeLayerInfo("lemon", 950));
43+
cakeBakingService.saveNewLayer(new CakeLayerInfo("vanilla", 950));
44+
cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));
45+
46+
cakeBakingService.saveNewTopping(new CakeToppingInfo("candies", 350));
47+
cakeBakingService.saveNewTopping(new CakeToppingInfo("cherry", 350));
48+
49+
var cake1 = new CakeInfo(new CakeToppingInfo("candies", 0), List.of(
50+
new CakeLayerInfo("chocolate", 0),
51+
new CakeLayerInfo("banana", 0),
52+
new CakeLayerInfo(STRAWBERRY, 0)));
53+
try {
54+
cakeBakingService.bakeNewCake(cake1);
55+
} catch (CakeBakingException e) {
56+
LOGGER.error("Cake baking exception", e);
57+
}
58+
var cake2 = new CakeInfo(new CakeToppingInfo("cherry", 0), List.of(
59+
new CakeLayerInfo("vanilla", 0),
60+
new CakeLayerInfo("lemon", 0),
61+
new CakeLayerInfo(STRAWBERRY, 0)));
62+
try {
63+
cakeBakingService.bakeNewCake(cake2);
64+
} catch (CakeBakingException e) {
65+
LOGGER.error("Cake baking exception", e);
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)