update 'Spring Boot' course
@@ -5,61 +5,60 @@ weight: 3
|
|||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
|
|
||||||
* Solid understanding of Java
|
Before diving in, make sure you're comfortable with the following:
|
||||||
* Object-oriented programming
|
|
||||||
* Classes, methods and interfaces
|
|
||||||
* Basic understanding of databases
|
|
||||||
* Tables, primary keys, foreign keys, relationships, etc.
|
|
||||||
* Write basic SQL statements
|
|
||||||
|
|
||||||
---
|
- **Java** — solid understanding of the language
|
||||||
|
- **Object-oriented programming** — classes, methods and interfaces
|
||||||
|
- **Databases** — tables, primary keys, foreign keys, relationships, etc.
|
||||||
|
- **SQL** — ability to write basic SQL statements
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# What is a Spring Framework?
|
# What is a Spring Framework?
|
||||||
|
|
||||||
**Spring** -- is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into few different layers.
|
**Spring** is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into a few different layers.
|
||||||
|
|
||||||

|

|
||||||
*Img. 1 -- Spring layers*
|
*Img. 1 — Spring layers*
|
||||||
|
|
||||||
| **Layer** | **Purpose** |
|
| **Layer** | **Purpose** |
|
||||||
| ------------- | -------------- |
|
|-----------|-------------|
|
||||||
| *Core* | Handling dependency injection, managing objects |
|
| *Core* | Handling dependency injection, managing objects |
|
||||||
| *Web* | Building web applications |
|
| *Web* | Building web applications |
|
||||||
| *Data* | Working with databases |
|
| *Data* | Working with databases |
|
||||||
| *AOP* | Aspect oriented programming |
|
| *AOP* | Aspect oriented programming |
|
||||||
| *Test* | Testing spring components |
|
| *Test* | Testing spring components |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
While the spring framework is powerfull, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That's when **Spring Boot** comes in.
|
While the Spring Framework is powerful, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That's when **Spring Boot** comes in.
|
||||||
|
|
||||||
You can think of spring boot as a layer on top of the spring framework, that takes care of all of the setup.
|
> [!NOTE]
|
||||||
|
> You can think of Spring Boot as a layer on top of the Spring Framework that takes care of all of the setup. *Spring Boot* simplifies Spring development by providing sensible defaults and ready-to-use features.
|
||||||
|
|
||||||
*Sring Boot* siplifies Spring development by providing sensible defaults and ready-to-use features.
|
By the way, the Spring Framework is just one part of a larger family of projects in the **Spring ecosystem**.
|
||||||
|
|
||||||
By the way, the spring framework is just one part of a larger family of projects in the spring ecosystem.
|

|
||||||
|
*Img. 2 — Spring ecosystem*
|
||||||
|
|
||||||

|
| **Module Name** | **Purpose** |
|
||||||
*Img. 2 -- Spring ecosystem*
|
|------------------------|-------------|
|
||||||
|
| *Spring Data* | Simplifying database access |
|
||||||
|
| *Spring Security* | Adding authentication and authorization |
|
||||||
|
| *Spring Batch* | Batch processing |
|
||||||
|
| *Spring Cloud* | Building microservices and distributed systems |
|
||||||
|
| *Spring Integration* | Simplifying messaging and integration between systems |
|
||||||
|
|
||||||
| **Module Name** | **Purpose** |
|
---
|
||||||
| ------------- | -------------- |
|
|
||||||
| *Spring Data* | Simplifying database access |
|
|
||||||
| *Spring Security* | Adding authentication and authorization |
|
|
||||||
| *Spring Batch* | Batch processing |
|
|
||||||
| *Spring Cloud* | Building microservices and distributed systems |
|
|
||||||
| *Spring Integration* | Symplifying messaging and integration between systems |
|
|
||||||
|
|
||||||
---
|
# Initialize Spring Boot Project
|
||||||
|
|
||||||
# Initialize Spring Boot Project
|
To initialize a new Spring Boot project, go to [start.spring.io](https://start.spring.io/) and select the options that suit you.
|
||||||
|
|
||||||
To initialize a new spring boot project you can go to [start.spring.io](https://start.spring.io/) and select options that suits you.
|
|
||||||
|
|
||||||

|

|
||||||
*Img. 3 -- Spring Boot options*
|
*Img. 3 — Spring Boot options*
|
||||||
|
|
||||||
After unpacking the `zip` arvhive we have this template project.
|
After unpacking the `zip` archive, you'll have this template project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
.
|
.
|
||||||
@@ -70,23 +69,23 @@ After unpacking the `zip` arvhive we have this template project.
|
|||||||
├── src
|
├── src
|
||||||
│ ├── main
|
│ ├── main
|
||||||
│ │ ├── java
|
│ │ ├── java
|
||||||
│ │ │ └── us
|
│ │ │ └── tech
|
||||||
│ │ │ └── fymio
|
│ │ │ └── codejava
|
||||||
│ │ │ └── store
|
│ │ │ └── store
|
||||||
│ │ │ └── StoreApplication.java
|
│ │ │ └── StoreApplication.java
|
||||||
│ │ └── resources
|
│ │ └── resources
|
||||||
│ │ └── application.properties
|
│ │ └── application.properties
|
||||||
│ └── test
|
│ └── test
|
||||||
│ └── java
|
│ └── java
|
||||||
│ └── us
|
│ └── tech
|
||||||
│ └── fymio
|
│ └── codejava
|
||||||
│ └── store
|
│ └── store
|
||||||
│ └── StoreApplicationTests.java
|
│ └── StoreApplicationTests.java
|
||||||
└── target
|
└── target
|
||||||
├── classes
|
├── classes
|
||||||
│ ├── application.properties
|
│ ├── application.properties
|
||||||
│ └── us
|
│ └── tech
|
||||||
│ └── fymio
|
│ └── codejava
|
||||||
│ └── store
|
│ └── store
|
||||||
│ └── StoreApplication.class
|
│ └── StoreApplication.class
|
||||||
├── generated-sources
|
├── generated-sources
|
||||||
@@ -104,16 +103,16 @@ After unpacking the `zip` arvhive we have this template project.
|
|||||||
│ ├── createdFiles.lst
|
│ ├── createdFiles.lst
|
||||||
│ └── inputFiles.lst
|
│ └── inputFiles.lst
|
||||||
├── surefire-reports
|
├── surefire-reports
|
||||||
│ ├── TEST-us.fymio.store.StoreApplicationTests.xml
|
│ ├── TEST-tech.codejava.store.StoreApplicationTests.xml
|
||||||
│ └── us.fymio.store.StoreApplicationTests.txt
|
│ └── tech.codejava.store.StoreApplicationTests.txt
|
||||||
└── test-classes
|
└── test-classes
|
||||||
└── us
|
└── tech
|
||||||
└── fymio
|
└── codejava
|
||||||
└── store
|
└── store
|
||||||
└── StoreApplicationTests.class
|
└── StoreApplicationTests.class
|
||||||
```
|
```
|
||||||
|
|
||||||
The "heart" of our project is the file named `pom.xml`:
|
The "heart" of our project is `pom.xml`:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
@@ -122,85 +121,85 @@ The "heart" of our project is the file named `pom.xml`:
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
>
|
>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>4.0.2</version>
|
<version>4.0.2</version>
|
||||||
<relativePath /> <!-- lookup parent from repository -->
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>us.fymio</groupId>
|
<groupId>tech.codejava</groupId>
|
||||||
<artifactId>store</artifactId>
|
<artifactId>store</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>store</name>
|
<name>store</name>
|
||||||
<description>Store</description>
|
<description>Store</description>
|
||||||
<url />
|
<url />
|
||||||
<licenses>
|
<licenses>
|
||||||
<license />
|
<license />
|
||||||
</licenses>
|
</licenses>
|
||||||
<developers>
|
<developers>
|
||||||
<developer />
|
<developer />
|
||||||
</developers>
|
</developers>
|
||||||
<scm>
|
<scm>
|
||||||
<connection />
|
<connection />
|
||||||
<developerConnection />
|
<developerConnection />
|
||||||
<tag />
|
<tag />
|
||||||
<url />
|
<url />
|
||||||
</scm>
|
</scm>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
```
|
```
|
||||||
|
|
||||||
Maven uses this file to download dependencies and build our project.
|
Maven uses this file to download dependencies and build our project.
|
||||||
|
|
||||||
In the `source` folder we have the actual code for our project.
|
In the `src` folder we have the actual code:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
src
|
src
|
||||||
├── main
|
├── main
|
||||||
│ ├── java
|
│ ├── java
|
||||||
│ │ └── us
|
│ │ └── tech
|
||||||
│ │ └── fymio
|
│ │ └── codejava
|
||||||
│ │ └── store
|
│ │ └── store
|
||||||
│ │ └── StoreApplication.java
|
│ │ └── StoreApplication.java
|
||||||
│ └── resources
|
│ └── resources
|
||||||
│ └── application.properties
|
│ └── application.properties
|
||||||
└── test
|
└── test
|
||||||
└── java
|
└── java
|
||||||
└── us
|
└── tech
|
||||||
└── fymio
|
└── codejava
|
||||||
└── store
|
└── store
|
||||||
└── StoreApplicationTests.java
|
└── StoreApplicationTests.java
|
||||||
```
|
```
|
||||||
|
|
||||||
The `StoreApplication.java` file is the entry point to our application.
|
`StoreApplication.java` is the entry point to our application:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package us.fymio.store;
|
package tech.codejava.store;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
@@ -208,20 +207,20 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class StoreApplication {
|
public class StoreApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(StoreApplication.class, args);
|
SpringApplication.run(StoreApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In the `main` method we have a call to `SpringApplication.run` method.
|
In the `main` method we have a call to `SpringApplication.run`.
|
||||||
|
|
||||||
If we run `mvn clean install` from the root of our project we will get this result (the output is partially reduced):
|
Running `mvn clean install` from the root of our project gives us this result *(output partially reduced)*:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
...
|
...
|
||||||
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.542 s -- in us.fymio.store.StoreApplicationTests
|
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.542 s -- in tech.codejava.store.StoreApplicationTests
|
||||||
[INFO]
|
[INFO]
|
||||||
[INFO] Results:
|
[INFO] Results:
|
||||||
[INFO]
|
[INFO]
|
||||||
@@ -233,10 +232,6 @@ If we run `mvn clean install` from the root of our project we will get this resu
|
|||||||
[INFO]
|
[INFO]
|
||||||
[INFO] --- spring-boot:4.0.2:repackage (repackage) @ store ---
|
[INFO] --- spring-boot:4.0.2:repackage (repackage) @ store ---
|
||||||
...
|
...
|
||||||
...
|
|
||||||
[INFO] Installing /home/fymio/store/pom.xml to /home/fymio/.m2/repository/us/fymio/store/0.0.1-SNAPSHOT/store-0.0.1-SNAPSHOT.pom
|
|
||||||
[INFO] Installing /home/fymio/store/target/store-0.0.1-SNAPSHOT.jar to /home/fymio/.m2/repository/us/fymio/store/0.0.1-SNAPSHOT/store-0.0.1-SNAPSHOT.jar
|
|
||||||
[INFO] ------------------------------------------------------------------------
|
|
||||||
[INFO] BUILD SUCCESS
|
[INFO] BUILD SUCCESS
|
||||||
[INFO] ------------------------------------------------------------------------
|
[INFO] ------------------------------------------------------------------------
|
||||||
[INFO] Total time: 14.787 s
|
[INFO] Total time: 14.787 s
|
||||||
@@ -244,18 +239,20 @@ If we run `mvn clean install` from the root of our project we will get this resu
|
|||||||
[INFO] ------------------------------------------------------------------------
|
[INFO] ------------------------------------------------------------------------
|
||||||
```
|
```
|
||||||
|
|
||||||
So we can tell that our application was built without errors.
|
Our application built without errors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Dependency Management
|
# Dependency Management
|
||||||
|
|
||||||
Dependencies are third-party libraries or frameworks we use in our application. For example to build a web application we need an embedded web server like *Tomcat*, we need libraries for handling web requests building APIs, processing JSON data, logging and so on.
|
Dependencies are third-party libraries or frameworks we use in our application. For example, to build a web application we need an embedded web server like *Tomcat*, libraries for handling web requests, building APIs, processing JSON data, logging and so on.
|
||||||
|
|
||||||
In spring boot applications instead of adding multiple individual libraries we can use a **starter dependency**.
|
In Spring Boot applications, instead of adding multiple individual libraries, we can use a **starter dependency**.
|
||||||
|
|
||||||

|

|
||||||
*Img. 5 -- Spring Boot Starter Web*
|
*Img. 5 — Spring Boot Starter Web*
|
||||||
|
|
||||||
To use this dependency we just need to copy the code below to our `pom.xml` file.
|
To use this dependency, copy the following into your `pom.xml`:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -265,53 +262,54 @@ To use this dependency we just need to copy the code below to our `pom.xml` file
|
|||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
So the `dependencies` section would look like this
|
So the `dependencies` section would look like this:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
<!-- <version>4.1.0-M1</version> -->
|
<!-- <version>4.1.0-M1</version> -->
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice, that I commented out the version of our dependency. That's because it's a better practice to let Spring Boot decide what version of the dependency to use.
|
> [!IMPORTANT]
|
||||||
|
> Notice that the version is commented out. It's a better practice to let Spring Boot decide what version of the dependency to use, as it ensures compatibility across your project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Controllers
|
# Controllers
|
||||||
|
|
||||||
**Spring MVC** stands for *Model View Controller*.
|
**Spring MVC** stands for *Model View Controller*.
|
||||||
|
|
||||||
*Model* is where our application's data lives. It represents the business logic and is usually connected to a database or other data sources. In spring boot the model can be a simple java class.
|
- **Model** is where our application's data lives. It represents the business logic and is usually connected to a database or other data sources. In Spring Boot, the model can be a simple Java class.
|
||||||
|
- **View** is what the user sees. It's the HTML, CSS or JavaScript rendered in the browser. In Spring MVC, views can be static files or dynamically generated.
|
||||||
|
- **Controller** is like a traffic controller. It handles incoming requests from the user, interacts with the model to get data and then tells the view what to display.
|
||||||
|
|
||||||
*View* is what the user sees. It's the HTML, CSS or JavaScript that's rendered in the browser. In Spring MVC views can be static files or dynamically generated.
|
Let's add a new Java class called `HomeController` at `src/main/java/tech/codejava/store/HomeController.java`:
|
||||||
|
|
||||||
*Controller* is like a traffic controller. It handles incoming requests from the user, interacts with the model to get data and then tells the view what to display.
|
|
||||||
|
|
||||||
Let's add a new java class called `HomeController`. It will be located at `src/main/java/us/fymio/store/HomeController.java`.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package us.fymio.store;
|
package tech.codejava.store;
|
||||||
|
|
||||||
public class HomeController {}
|
public class HomeController {}
|
||||||
```
|
```
|
||||||
|
|
||||||
To make this a controller we have to decorate it with the controller annotation. And import the `Controller` from `org.springframework.stereotype` package.
|
To make this a controller, decorate it with the `@Controller` annotation:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package us.fymio.store;
|
package tech.codejava.store;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
|
||||||
@@ -319,10 +317,10 @@ import org.springframework.stereotype.Controller;
|
|||||||
public class HomeController {}
|
public class HomeController {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's now add an `index` method. When we send a request to the root of our website we want this method to be called. Also we need to add another special annotation to this method.
|
Now let's add an `index` method. When we send a request to the root of our website, we want this method to be called:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package us.fymio.store;
|
package tech.codejava.store;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -337,7 +335,7 @@ public class HomeController {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we need to create this view. We add the `index.html` at `src/main/resources/static/index.html`. For now let's just print "Hello world!".
|
Now we need to create the view. Add `index.html` at `src/main/resources/static/index.html`:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -353,33 +351,31 @@ Now we need to create this view. We add the `index.html` at `src/main/resources/
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
Now let's build our application using `mvn spring-boot:run`.
|
Let's build and run our application using `mvn spring-boot:run`. From the logs:
|
||||||
|
|
||||||
As we can see from the logs:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
2026-02-19T14:55:23.948+03:00 INFO 36752 --- [store] [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
2026-02-19T14:55:23.948+03:00 INFO 36752 --- [store] [ main] o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
|
||||||
```
|
```
|
||||||
|
|
||||||
It means that our app is up and running at [localhost:8080](http://localhost:8080/).
|
Our app is up and running at [localhost:8080](http://localhost:8080/).
|
||||||
|
|
||||||

|

|
||||||
*Img. 7 -- Our app is up and running!*
|
*Img. 7 — Our app is up and running!*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Configuring Application Properties
|
# Configuring Application Properties
|
||||||
|
|
||||||
Let's take a look at our `application.properties` file located at `src/main/resources/application.properties`.
|
Let's take a look at `src/main/resources/application.properties`:
|
||||||
|
|
||||||
```properties
|
```properties
|
||||||
spring.application.name=store
|
spring.application.name=store
|
||||||
```
|
```
|
||||||
|
|
||||||
To use this property in our code we can use the `@Value` annotation.
|
To use this property in our code, we can use the `@Value` annotation. Let's update `HomeController` to print the application name:
|
||||||
|
|
||||||
Let's change our `HomeController` class so it prints the name of our application.
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package us.fymio.store;
|
package tech.codejava.store;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
@@ -399,19 +395,276 @@ public class HomeController {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And as we can see after running our application there is a `store` printed out in the terminal.
|
After running the application, we can see `store` printed in the terminal:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
...
|
...
|
||||||
2026-02-19T15:32:37.507+03:00 INFO 41536 --- [store] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
|
2026-02-19T15:32:37.507+03:00 INFO 41536 --- [store] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
|
||||||
2026-02-19T15:32:37.509+03:00 INFO 41536 --- [store] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
|
2026-02-19T15:32:37.509+03:00 INFO 41536 --- [store] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
|
||||||
application name = store
|
application name = store
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
# Dependency injection
|
---
|
||||||
|
|
||||||
Imagine we are building an E-Commerce application that handles placing orders. When the order is placed, the customer's payment needs to be processed so order service depends on a payment service like stripe payment service. In this case we can say that order service is *dependent* or *coupled to* stripe payment service.
|
# Dependency Injection
|
||||||
|
|
||||||

|
Imagine we're building an E-Commerce application that handles placing orders. When an order is placed, the customer's payment needs to be processed — so `OrderService` depends on a payment service like `StripePaymentService`. We can say that `OrderService` is *dependent on* (or *coupled to*) `StripePaymentService`.
|
||||||
*Img. 8 -- Depends On/Coupled To relation.*
|
|
||||||
|

|
||||||
|
*Img. 8 — Depends On/Coupled To relation*
|
||||||
|
|
||||||
|
Let's talk about the issues that arise when one class is **tightly coupled** to another.
|
||||||
|
|
||||||
|
1. **Inflexibility** — `OrderService` can only use `StripePaymentService`. If tomorrow we decide to switch to a different payment provider like PayPal, we would have to modify `OrderService`. Once we change it, it has to be recompiled and retested, which could impact other classes that depend on it.
|
||||||
|
2. **Untestability** — We cannot test `OrderService` in isolation, because `OrderService` is tightly coupled with `StripePaymentService` and we can't test its logic separately from it.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> The problem here isn't that `OrderService` *depends* on `StripePaymentService` — dependencies are normal in any application. The issue is about *how* the dependency is created and managed.
|
||||||
|
|
||||||
|
**Analogy:** Think of a restaurant. A restaurant needs a chef — that's a perfectly normal dependency. If the current chef becomes unavailable, the restaurant can hire another one.
|
||||||
|
|
||||||
|

|
||||||
|
*Img. X — Restaurant — Chef dependency (Normal)*
|
||||||
|
|
||||||
|
Now what if we replace "chef" with a specific person: John? Our restaurant is now dependent on *John specifically*. If John becomes unavailable, we can't replace him — the restaurant is in trouble. This is an example of **tight** or **bad coupling**.
|
||||||
|
|
||||||
|

|
||||||
|
*Img. X — Restaurant — John dependency (Bad coupling)*
|
||||||
|
|
||||||
|
We don't want `OrderService` to be tightly coupled to a specific payment service like Stripe. Instead, we want it to depend on a `PaymentService` *interface*, which could be Stripe, PayPal, or any other provider. To achieve this we can use the *interface* to decouple `OrderService` from `StripePaymentService`.
|
||||||
|
|
||||||
|

|
||||||
|
*Img. X — `PaymentService` as `interface`*
|
||||||
|
|
||||||
|
If `OrderService` depends on a `PaymentService` interface, it doesn't know anything about Stripe, PayPal, or any other payment provider. As long as these providers implement `PaymentService`, they can be used to handle payments — and `OrderService` won't care which one is being used.
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
|
||||||
|
1. If we replace `StripePaymentService` with `PayPalPaymentService`, the `OrderService` class is not affected.
|
||||||
|
2. We don't need to modify or recompile `OrderService`.
|
||||||
|
3. We can test `OrderService` in isolation, without relying on the specific payment provider like Stripe.
|
||||||
|
|
||||||
|
With this setup, we simply give `OrderService` a particular implementation of `PaymentService`. This is called **dependency injection** — we *inject* the dependency into a class.
|
||||||
|
|
||||||
|

|
||||||
|
*Img. X — Dependency Injection example*
|
||||||
|
|
||||||
|
Let's see how it works in our project. Create `OrderService` at `src/main/java/tech/codejava/store/OrderService.java`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
public void placeOrder() {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> In a real project we would need to provide something like `Order order` to this method, but for teaching purposes we won't do that.
|
||||||
|
|
||||||
|
Now create `StripePaymentService` in the same directory:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class StripePaymentService {
|
||||||
|
|
||||||
|
public void processPayment(double amount) {
|
||||||
|
System.out.println("=== STRIPE ===");
|
||||||
|
System.out.println("amount: " + amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's implement `placeOrder` in `OrderService` using `StripePaymentService`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
public void placeOrder() {
|
||||||
|
var paymentService = new StripePaymentService();
|
||||||
|
paymentService.processPayment(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is our *before* setup — before we introduced the interface. In this implementation, `OrderService` is **tightly coupled** to `StripePaymentService`. We cannot test `OrderService` in isolation, and switching to another payment provider would require modifying `OrderService`.
|
||||||
|
|
||||||
|
Let's fix this. Create a `PaymentService` interface in the same directory:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public interface PaymentService {
|
||||||
|
void processPayment(double amount);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Modify `StripePaymentService` to implement `PaymentService`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class StripePaymentService implements PaymentService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processPayment(double amount) {
|
||||||
|
System.out.println("=== STRIPE ===");
|
||||||
|
System.out.println("amount: " + amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The recommended way to inject a dependency into a class is via its **constructor**. Let's define one in `OrderService`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
private PaymentService paymentService;
|
||||||
|
|
||||||
|
public OrderService(PaymentService paymentService) {
|
||||||
|
this.paymentService = paymentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void placeOrder() {
|
||||||
|
paymentService.processPayment(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now let's see this in action. Modify `StoreApplication`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class StoreApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// SpringApplication.run(StoreApplication.class, args);
|
||||||
|
|
||||||
|
var orderService = new OrderService(new StripePaymentService());
|
||||||
|
orderService.placeOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Running the application *(output intentionally reduced)*:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
...
|
||||||
|
=== STRIPE ===
|
||||||
|
amount: 10.0
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Now let's create a `PayPalPaymentService` in the same directory:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class PayPalPaymentService implements PaymentService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processPayment(double amount) {
|
||||||
|
System.out.println("=== PayPal ===");
|
||||||
|
System.out.println("amount: " + amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now we can switch from `StripePaymentService` to `PayPalPaymentService` in `StoreApplication` — without touching `OrderService` at all:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class StoreApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// SpringApplication.run(StoreApplication.class, args);
|
||||||
|
|
||||||
|
// var orderService = new OrderService(new StripePaymentService());
|
||||||
|
var orderService = new OrderService(new PayPalPaymentService());
|
||||||
|
orderService.placeOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
...
|
||||||
|
=== PayPal ===
|
||||||
|
amount: 10.0
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that we didn't change `OrderService`. In *object-oriented programming* this is known as the **Open/Closed Principle**:
|
||||||
|
|
||||||
|
> A class should be open for extension and closed for modification.
|
||||||
|
|
||||||
|
In other words: we should be able to add new functionality to a class without changing its existing code. This reduces the risk of introducing bugs and breaking other parts of the application.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Setter Injection
|
||||||
|
|
||||||
|
Another way to inject a dependency is via a **setter**. In `OrderService`, let's define one:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
public class OrderService {
|
||||||
|
|
||||||
|
private PaymentService paymentService;
|
||||||
|
|
||||||
|
public void setPaymentService(PaymentService paymentService) {
|
||||||
|
this.paymentService = paymentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderService(PaymentService paymentService) {
|
||||||
|
this.paymentService = paymentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void placeOrder() {
|
||||||
|
paymentService.processPayment(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We can use it like this in `StoreApplication`:
|
||||||
|
|
||||||
|
```java
|
||||||
|
package tech.codejava.store;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class StoreApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// SpringApplication.run(StoreApplication.class, args);
|
||||||
|
|
||||||
|
// var orderService = new OrderService(new StripePaymentService());
|
||||||
|
var orderService = new OrderService(new PayPalPaymentService());
|
||||||
|
orderService.setPaymentService(new PayPalPaymentService());
|
||||||
|
orderService.placeOrder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> If you remove the constructor from `OrderService` and forget to call the setter, the application will crash with a `NullPointerException`. Use setter injection only for **optional** dependencies — ones that `OrderService` can function without.
|
||||||
|
|||||||
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -9,9 +9,8 @@
|
|||||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
|
||||||
<link fetchpriority="low" href="/site.webmanifest" rel="manifest" />
|
<link fetchpriority="low" href="/site.webmanifest" rel="manifest" />
|
||||||
<title>CodeJava</title>
|
<title>CodeJava</title>
|
||||||
<meta name="description" content="Prerequisites Solid understanding of Java Object-oriented programming Classes, methods and interfaces Basic understanding of databases Tables, primary keys, foreign keys, relationships, etc. Write basic SQL statements What is a Spring Framework?Spring – is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into few different layers.
|
<meta name="description" content="PrerequisitesBefore diving in, make sure you’re comfortable with the following:
|
||||||
Img. 1 – Spring layers
|
Java — solid understanding of the language Object-oriented programming — classes, methods and interfaces Databases — tables, primary keys, foreign keys, relationships, etc. SQL — ability to write basic SQL statements What is a Spring Framework?Spring is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into a few different layers." /><link rel="canonical" href="http://localhost:1313/courses/spring-boot/" itemprop="url" />
|
||||||
Layer Purpose Core Handling dependency injection, managing objects Web Building web applications Data Working with databases AOP Aspect oriented programming Test Testing spring components While the spring framework is powerfull, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That’s when Spring Boot comes in." /><link rel="canonical" href="http://localhost:1313/courses/spring-boot/" itemprop="url" />
|
|
||||||
|
|
||||||
<meta property="og:title" content="">
|
<meta property="og:title" content="">
|
||||||
<meta
|
<meta
|
||||||
@@ -30,15 +29,13 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
|
|
||||||
|
|
||||||
<meta itemprop="name" content="CodeJava">
|
<meta itemprop="name" content="CodeJava">
|
||||||
<meta itemprop="description" content="Prerequisites Solid understanding of Java Object-oriented programming Classes, methods and interfaces Basic understanding of databases Tables, primary keys, foreign keys, relationships, etc. Write basic SQL statements What is a Spring Framework?Spring – is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into few different layers.
|
<meta itemprop="description" content="PrerequisitesBefore diving in, make sure you’re comfortable with the following:
|
||||||
Img. 1 – Spring layers
|
Java — solid understanding of the language Object-oriented programming — classes, methods and interfaces Databases — tables, primary keys, foreign keys, relationships, etc. SQL — ability to write basic SQL statements What is a Spring Framework?Spring is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into a few different layers.">
|
||||||
Layer Purpose Core Handling dependency injection, managing objects Web Building web applications Data Working with databases AOP Aspect oriented programming Test Testing spring components While the spring framework is powerfull, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That’s when Spring Boot comes in.">
|
<meta itemprop="wordCount" content="2184">
|
||||||
<meta itemprop="wordCount" content="1348">
|
|
||||||
<meta name="twitter:card" content="summary">
|
<meta name="twitter:card" content="summary">
|
||||||
<meta name="twitter:title" content="CodeJava">
|
<meta name="twitter:title" content="CodeJava">
|
||||||
<meta name="twitter:description" content="Prerequisites Solid understanding of Java Object-oriented programming Classes, methods and interfaces Basic understanding of databases Tables, primary keys, foreign keys, relationships, etc. Write basic SQL statements What is a Spring Framework?Spring – is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into few different layers.
|
<meta name="twitter:description" content="PrerequisitesBefore diving in, make sure you’re comfortable with the following:
|
||||||
Img. 1 – Spring layers
|
Java — solid understanding of the language Object-oriented programming — classes, methods and interfaces Databases — tables, primary keys, foreign keys, relationships, etc. SQL — ability to write basic SQL statements What is a Spring Framework?Spring is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into a few different layers.">
|
||||||
Layer Purpose Core Handling dependency injection, managing objects Web Building web applications Data Working with databases AOP Aspect oriented programming Test Testing spring components While the spring framework is powerfull, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That’s when Spring Boot comes in.">
|
|
||||||
<link href="/css/compiled/main.css" rel="stylesheet" />
|
<link href="/css/compiled/main.css" rel="stylesheet" />
|
||||||
<link href="/css/variables.css" rel="stylesheet" />
|
<link href="/css/variables.css" rel="stylesheet" />
|
||||||
<link href="/css/custom.css" rel="stylesheet" />
|
<link href="/css/custom.css" rel="stylesheet" />
|
||||||
@@ -169,7 +166,13 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
>Spring Boot
|
>Spring Boot
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<ul class='hx:flex hx:flex-col hx:gap-1 hx:relative hx:before:absolute hx:before:inset-y-1 hx:before:w-px hx:before:bg-gray-200 hx:before:content-[""] hx:dark:before:bg-neutral-800 hx:ltr:pl-3 hx:ltr:before:left-0 hx:rtl:pr-3 hx:rtl:before:right-0 hx:ltr:ml-3 hx:rtl:mr-3'></ul>
|
<ul class='hx:flex hx:flex-col hx:gap-1 hx:relative hx:before:absolute hx:before:inset-y-1 hx:before:w-px hx:before:bg-gray-200 hx:before:content-[""] hx:dark:before:bg-neutral-800 hx:ltr:pl-3 hx:ltr:before:left-0 hx:rtl:pr-3 hx:rtl:before:right-0 hx:ltr:ml-3 hx:rtl:mr-3'><li>
|
||||||
|
<a
|
||||||
|
href="#setter-injection"
|
||||||
|
class="hx:flex hx:rounded-sm hx:px-2 hx:py-1.5 hx:text-sm hx:transition-colors [word-break:break-word] hx:cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] hx:contrast-more:border hx:gap-2 hx:before:opacity-25 hx:before:content-['#'] hx:text-gray-500 hx:hover:bg-gray-100 hx:hover:text-gray-900 hx:dark:text-neutral-400 hx:dark:hover:bg-primary-100/5 hx:dark:hover:text-gray-50 hx:contrast-more:text-gray-900 hx:contrast-more:dark:text-gray-50 hx:contrast-more:border-transparent hx:contrast-more:hover:border-gray-900 hx:contrast-more:dark:hover:border-gray-50"
|
||||||
|
>Setter Injection</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
</li><li class="hx:flex hx:flex-col "><a
|
</li><li class="hx:flex hx:flex-col "><a
|
||||||
@@ -330,7 +333,11 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</div></div></div></aside>
|
</div></div></div></aside>
|
||||||
|
|
||||||
<nav class="hextra-toc hx:order-last hx:hidden hx:w-64 hx:shrink-0 hx:xl:block hx:print:hidden hx:px-4" aria-label="table of contents">
|
<nav class="hextra-toc hx:order-last hx:hidden hx:w-64 hx:shrink-0 hx:xl:block hx:print:hidden hx:px-4" aria-label="table of contents">
|
||||||
<div class="hextra-scrollbar hx:sticky hx:top-16 hx:overflow-y-auto hx:pr-4 hx:pt-6 hx:text-sm [hyphens:auto] hx:max-h-[calc(100vh-var(--navbar-height)-env(safe-area-inset-bottom))] hx:ltr:-mr-4 hx:rtl:-ml-4"><p class="hx:mb-4 hx:font-semibold hx:tracking-tight">On this page</p><ul></ul><ul></ul><ul></ul><ul></ul><ul></ul><ul></ul><ul></ul>
|
<div class="hextra-scrollbar hx:sticky hx:top-16 hx:overflow-y-auto hx:pr-4 hx:pt-6 hx:text-sm [hyphens:auto] hx:max-h-[calc(100vh-var(--navbar-height)-env(safe-area-inset-bottom))] hx:ltr:-mr-4 hx:rtl:-ml-4"><p class="hx:mb-4 hx:font-semibold hx:tracking-tight">On this page</p><ul></ul><ul></ul><ul></ul><ul></ul><ul></ul><ul></ul><ul>
|
||||||
|
<li class="hx:my-2 hx:scroll-my-6 hx:scroll-py-6">
|
||||||
|
<a class="hx:font-medium hx:inline-block hx:text-gray-500 hx:hover:text-gray-900 hx:dark:text-gray-400 hx:dark:hover:text-gray-300 hx:contrast-more:text-gray-900 hx:contrast-more:underline hx:contrast-more:dark:text-gray-50 hx:w-full hx:break-words" href="#setter-injection">Setter Injection
|
||||||
|
</a>
|
||||||
|
</li></ul>
|
||||||
<div class="hx:mt-8 hx:border-t hx:bg-white hx:pt-8 hx:shadow-[0_-12px_16px_white] hx:dark:bg-dark hx:dark:shadow-[0_-12px_16px_#111] hx:sticky hx:bottom-0 hx:flex hx:flex-col hx:items-start hx:gap-2 hx:pb-8 hx:border-gray-200 hx:dark:border-neutral-800 hx:contrast-more:border-t hx:contrast-more:border-neutral-400 hx:contrast-more:shadow-none hx:contrast-more:dark:border-neutral-400">
|
<div class="hx:mt-8 hx:border-t hx:bg-white hx:pt-8 hx:shadow-[0_-12px_16px_white] hx:dark:bg-dark hx:dark:shadow-[0_-12px_16px_#111] hx:sticky hx:bottom-0 hx:flex hx:flex-col hx:items-start hx:gap-2 hx:pb-8 hx:border-gray-200 hx:dark:border-neutral-800 hx:contrast-more:border-t hx:contrast-more:border-neutral-400 hx:contrast-more:shadow-none hx:contrast-more:dark:border-neutral-400">
|
||||||
<button aria-hidden="true" id="backToTop" onClick="scrollUp();" class="hx:cursor-pointer hx:transition-all hx:duration-75 hx:opacity-0 hx:text-xs hx:font-medium hx:text-gray-500 hx:hover:text-gray-900 hx:dark:text-gray-400 hx:dark:hover:text-gray-100 hx:contrast-more:text-gray-800 hx:contrast-more:dark:text-gray-50">
|
<button aria-hidden="true" id="backToTop" onClick="scrollUp();" class="hx:cursor-pointer hx:transition-all hx:duration-75 hx:opacity-0 hx:text-xs hx:font-medium hx:text-gray-500 hx:hover:text-gray-900 hx:dark:text-gray-400 hx:dark:hover:text-gray-100 hx:contrast-more:text-gray-800 hx:contrast-more:dark:text-gray-50">
|
||||||
<span>Scroll to top</span>
|
<span>Scroll to top</span>
|
||||||
@@ -348,18 +355,17 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
||||||
<h1>Prerequisites</h1><ul>
|
<h1>Prerequisites</h1><p>Before diving in, make sure you’re comfortable with the following:</p>
|
||||||
<li>Solid understanding of Java</li>
|
<ul>
|
||||||
<li>Object-oriented programming</li>
|
<li><strong>Java</strong> — solid understanding of the language</li>
|
||||||
<li>Classes, methods and interfaces</li>
|
<li><strong>Object-oriented programming</strong> — classes, methods and interfaces</li>
|
||||||
<li>Basic understanding of databases</li>
|
<li><strong>Databases</strong> — tables, primary keys, foreign keys, relationships, etc.</li>
|
||||||
<li>Tables, primary keys, foreign keys, relationships, etc.</li>
|
<li><strong>SQL</strong> — ability to write basic SQL statements</li>
|
||||||
<li>Write basic SQL statements</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<hr>
|
||||||
<h1>What is a Spring Framework?</h1><p><strong>Spring</strong> – is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into few different layers.</p>
|
<h1>What is a Spring Framework?</h1><p><strong>Spring</strong> is a popular framework for building Java applications. It has a lot of modules, each designed to handle a specific task. They are combined into a few different layers.</p>
|
||||||
<p><img src="assets/spring-layers.svg" alt="Spring layers" loading="lazy" />
|
<p><img src="assets/spring-layers.svg" alt="Spring layers" loading="lazy" />
|
||||||
<em>Img. 1 – Spring layers</em></p>
|
<em>Img. 1 — Spring layers</em></p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -391,12 +397,17 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<p>While the spring framework is powerfull, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That’s when <strong>Spring Boot</strong> comes in.</p>
|
<p>While the Spring Framework is powerful, using it often involves a lot of configuration. For example, if you want to build a web app you might need to setup a web server, configure routing and manage dependencies manually. That’s when <strong>Spring Boot</strong> comes in.</p>
|
||||||
<p>You can think of spring boot as a layer on top of the spring framework, that takes care of all of the setup.</p>
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200">
|
||||||
<p><em>Sring Boot</em> siplifies Spring development by providing sensible defaults and ready-to-use features.</p>
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Note</p>
|
||||||
<p>By the way, the spring framework is just one part of a larger family of projects in the spring ecosystem.</p>
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>You can think of Spring Boot as a layer on top of the Spring Framework that takes care of all of the setup. <em>Spring Boot</em> simplifies Spring development by providing sensible defaults and ready-to-use features.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>By the way, the Spring Framework is just one part of a larger family of projects in the <strong>Spring ecosystem</strong>.</p>
|
||||||
<p><img src="assets/spring-ecosystem.svg" alt="Spring ecosystem" loading="lazy" />
|
<p><img src="assets/spring-ecosystem.svg" alt="Spring ecosystem" loading="lazy" />
|
||||||
<em>Img. 2 – Spring ecosystem</em></p>
|
<em>Img. 2 — Spring ecosystem</em></p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -423,15 +434,15 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><em>Spring Integration</em></td>
|
<td><em>Spring Integration</em></td>
|
||||||
<td>Symplifying messaging and integration between systems</td>
|
<td>Simplifying messaging and integration between systems</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
<h1>Initialize Spring Boot Project</h1><p>To initialize a new spring boot project you can go to <a href="https://start.spring.io/"target="_blank" rel="noopener">start.spring.io</a> and select options that suits you.</p>
|
<h1>Initialize Spring Boot Project</h1><p>To initialize a new Spring Boot project, go to <a href="https://start.spring.io/"target="_blank" rel="noopener">start.spring.io</a> and select the options that suit you.</p>
|
||||||
<p><img src="assets/spring-project-init.png" alt="Spring Options" loading="lazy" />
|
<p><img src="assets/spring-project-init.png" alt="Spring Options" loading="lazy" />
|
||||||
<em>Img. 3 – Spring Boot options</em></p>
|
<em>Img. 3 — Spring Boot options</em></p>
|
||||||
<p>After unpacking the <code>zip</code> arvhive we have this template project.</p>
|
<p>After unpacking the <code>zip</code> archive, you’ll have this template project:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>.
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>.
|
||||||
@@ -442,23 +453,23 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</span></span><span style="display:flex;"><span>├── src
|
</span></span><span style="display:flex;"><span>├── src
|
||||||
</span></span><span style="display:flex;"><span>│ ├── main
|
</span></span><span style="display:flex;"><span>│ ├── main
|
||||||
</span></span><span style="display:flex;"><span>│ │ ├── java
|
</span></span><span style="display:flex;"><span>│ │ ├── java
|
||||||
</span></span><span style="display:flex;"><span>│ │ │ └── us
|
</span></span><span style="display:flex;"><span>│ │ │ └── tech
|
||||||
</span></span><span style="display:flex;"><span>│ │ │ └── fymio
|
</span></span><span style="display:flex;"><span>│ │ │ └── codejava
|
||||||
</span></span><span style="display:flex;"><span>│ │ │ └── store
|
</span></span><span style="display:flex;"><span>│ │ │ └── store
|
||||||
</span></span><span style="display:flex;"><span>│ │ │ └── StoreApplication.java
|
</span></span><span style="display:flex;"><span>│ │ │ └── StoreApplication.java
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── resources
|
</span></span><span style="display:flex;"><span>│ │ └── resources
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── application.properties
|
</span></span><span style="display:flex;"><span>│ │ └── application.properties
|
||||||
</span></span><span style="display:flex;"><span>│ └── test
|
</span></span><span style="display:flex;"><span>│ └── test
|
||||||
</span></span><span style="display:flex;"><span>│ └── java
|
</span></span><span style="display:flex;"><span>│ └── java
|
||||||
</span></span><span style="display:flex;"><span>│ └── us
|
</span></span><span style="display:flex;"><span>│ └── tech
|
||||||
</span></span><span style="display:flex;"><span>│ └── fymio
|
</span></span><span style="display:flex;"><span>│ └── codejava
|
||||||
</span></span><span style="display:flex;"><span>│ └── store
|
</span></span><span style="display:flex;"><span>│ └── store
|
||||||
</span></span><span style="display:flex;"><span>│ └── StoreApplicationTests.java
|
</span></span><span style="display:flex;"><span>│ └── StoreApplicationTests.java
|
||||||
</span></span><span style="display:flex;"><span>└── target
|
</span></span><span style="display:flex;"><span>└── target
|
||||||
</span></span><span style="display:flex;"><span> ├── classes
|
</span></span><span style="display:flex;"><span> ├── classes
|
||||||
</span></span><span style="display:flex;"><span> │ ├── application.properties
|
</span></span><span style="display:flex;"><span> │ ├── application.properties
|
||||||
</span></span><span style="display:flex;"><span> │ └── us
|
</span></span><span style="display:flex;"><span> │ └── tech
|
||||||
</span></span><span style="display:flex;"><span> │ └── fymio
|
</span></span><span style="display:flex;"><span> │ └── codejava
|
||||||
</span></span><span style="display:flex;"><span> │ └── store
|
</span></span><span style="display:flex;"><span> │ └── store
|
||||||
</span></span><span style="display:flex;"><span> │ └── StoreApplication.class
|
</span></span><span style="display:flex;"><span> │ └── StoreApplication.class
|
||||||
</span></span><span style="display:flex;"><span> ├── generated-sources
|
</span></span><span style="display:flex;"><span> ├── generated-sources
|
||||||
@@ -476,11 +487,11 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</span></span><span style="display:flex;"><span> │ ├── createdFiles.lst
|
</span></span><span style="display:flex;"><span> │ ├── createdFiles.lst
|
||||||
</span></span><span style="display:flex;"><span> │ └── inputFiles.lst
|
</span></span><span style="display:flex;"><span> │ └── inputFiles.lst
|
||||||
</span></span><span style="display:flex;"><span> ├── surefire-reports
|
</span></span><span style="display:flex;"><span> ├── surefire-reports
|
||||||
</span></span><span style="display:flex;"><span> │ ├── TEST-us.fymio.store.StoreApplicationTests.xml
|
</span></span><span style="display:flex;"><span> │ ├── TEST-tech.codejava.store.StoreApplicationTests.xml
|
||||||
</span></span><span style="display:flex;"><span> │ └── us.fymio.store.StoreApplicationTests.txt
|
</span></span><span style="display:flex;"><span> │ └── tech.codejava.store.StoreApplicationTests.txt
|
||||||
</span></span><span style="display:flex;"><span> └── test-classes
|
</span></span><span style="display:flex;"><span> └── test-classes
|
||||||
</span></span><span style="display:flex;"><span> └── us
|
</span></span><span style="display:flex;"><span> └── tech
|
||||||
</span></span><span style="display:flex;"><span> └── fymio
|
</span></span><span style="display:flex;"><span> └── codejava
|
||||||
</span></span><span style="display:flex;"><span> └── store
|
</span></span><span style="display:flex;"><span> └── store
|
||||||
</span></span><span style="display:flex;"><span> └── StoreApplicationTests.class</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span> └── StoreApplicationTests.class</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -492,7 +503,7 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>The “heart” of our project is the file named <code>pom.xml</code>:</p>
|
<p>The “heart” of our project is <code>pom.xml</code>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e"><?xml version="1.0" encoding="UTF-8" ?></span>
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e"><?xml version="1.0" encoding="UTF-8" ?></span>
|
||||||
@@ -501,55 +512,55 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">></span>
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><modelVersion></span>4.0.0<span style="color:#f92672"></modelVersion></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><modelVersion></span>4.0.0<span style="color:#f92672"></modelVersion></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><parent></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><parent></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-parent<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-parent<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><version></span>4.0.2<span style="color:#f92672"></version></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><version></span>4.0.2<span style="color:#f92672"></version></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><relativePath</span> <span style="color:#f92672">/></span> <span style="color:#75715e"><!-- lookup parent from repository --></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><relativePath</span> <span style="color:#f92672">/></span> <span style="color:#75715e"><!-- lookup parent from repository --></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></parent></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></parent></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>us.fymio<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>tech.codejava<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>store<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>store<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><version></span>0.0.1-SNAPSHOT<span style="color:#f92672"></version></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><version></span>0.0.1-SNAPSHOT<span style="color:#f92672"></version></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><name></span>store<span style="color:#f92672"></name></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><name></span>store<span style="color:#f92672"></name></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><description></span>Store<span style="color:#f92672"></description></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><description></span>Store<span style="color:#f92672"></description></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><url</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><url</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><licenses></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><licenses></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><license</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><license</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></licenses></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></licenses></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developers></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developers></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developer</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developer</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></developers></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></developers></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scm></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scm></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><connection</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><connection</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developerConnection</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><developerConnection</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><tag</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><tag</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><url</span> <span style="color:#f92672">/></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><url</span> <span style="color:#f92672">/></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></scm></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></scm></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><properties></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><properties></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><java.version></span>21<span style="color:#f92672"></java.version></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><java.version></span>21<span style="color:#f92672"></java.version></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></properties></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></properties></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependencies></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependencies></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-test<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-test<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scope></span>test<span style="color:#f92672"></scope></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scope></span>test<span style="color:#f92672"></scope></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependencies></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependencies></span>
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><build></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><build></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><plugins></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><plugins></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><plugin></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><plugin></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-maven-plugin<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-maven-plugin<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></plugin></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></plugin></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></plugins></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></plugins></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></build></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></build></span>
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672"></project></span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span><span style="color:#f92672"></project></span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -562,22 +573,22 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Maven uses this file to download dependencies and build our project.</p>
|
<p>Maven uses this file to download dependencies and build our project.</p>
|
||||||
<p>In the <code>source</code> folder we have the actual code for our project.</p>
|
<p>In the <code>src</code> folder we have the actual code:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>src
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>src
|
||||||
</span></span><span style="display:flex;"><span>├── main
|
</span></span><span style="display:flex;"><span>├── main
|
||||||
</span></span><span style="display:flex;"><span>│ ├── java
|
</span></span><span style="display:flex;"><span>│ ├── java
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── us
|
</span></span><span style="display:flex;"><span>│ │ └── tech
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── fymio
|
</span></span><span style="display:flex;"><span>│ │ └── codejava
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── store
|
</span></span><span style="display:flex;"><span>│ │ └── store
|
||||||
</span></span><span style="display:flex;"><span>│ │ └── StoreApplication.java
|
</span></span><span style="display:flex;"><span>│ │ └── StoreApplication.java
|
||||||
</span></span><span style="display:flex;"><span>│ └── resources
|
</span></span><span style="display:flex;"><span>│ └── resources
|
||||||
</span></span><span style="display:flex;"><span>│ └── application.properties
|
</span></span><span style="display:flex;"><span>│ └── application.properties
|
||||||
</span></span><span style="display:flex;"><span>└── test
|
</span></span><span style="display:flex;"><span>└── test
|
||||||
</span></span><span style="display:flex;"><span> └── java
|
</span></span><span style="display:flex;"><span> └── java
|
||||||
</span></span><span style="display:flex;"><span> └── us
|
</span></span><span style="display:flex;"><span> └── tech
|
||||||
</span></span><span style="display:flex;"><span> └── fymio
|
</span></span><span style="display:flex;"><span> └── codejava
|
||||||
</span></span><span style="display:flex;"><span> └── store
|
</span></span><span style="display:flex;"><span> └── store
|
||||||
</span></span><span style="display:flex;"><span> └── StoreApplicationTests.java</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span> └── StoreApplicationTests.java</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -589,10 +600,10 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>The <code>StoreApplication.java</code> file is the entry point to our application.</p>
|
<p><code>StoreApplication.java</code> is the entry point to our application:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> us.fymio.store;
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.SpringApplication;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.SpringApplication;
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
@@ -600,9 +611,9 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@SpringBootApplication</span>
|
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@SpringBootApplication</span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StoreApplication</span> {
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StoreApplication</span> {
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
|
||||||
</span></span><span style="display:flex;"><span> SpringApplication.<span style="color:#a6e22e">run</span>(StoreApplication.<span style="color:#a6e22e">class</span>, args);
|
</span></span><span style="display:flex;"><span> SpringApplication.<span style="color:#a6e22e">run</span>(StoreApplication.<span style="color:#a6e22e">class</span>, args);
|
||||||
</span></span><span style="display:flex;"><span> }
|
</span></span><span style="display:flex;"><span> }
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -614,12 +625,12 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>In the <code>main</code> method we have a call to <code>SpringApplication.run</code> method.</p>
|
<p>In the <code>main</code> method we have a call to <code>SpringApplication.run</code>.</p>
|
||||||
<p>If we run <code>mvn clean install</code> from the root of our project we will get this result (the output is partially reduced):</p>
|
<p>Running <code>mvn clean install</code> from the root of our project gives us this result <em>(output partially reduced)</em>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.542 s -- in us.fymio.store.StoreApplicationTests
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.542 s -- in tech.codejava.store.StoreApplicationTests
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Results:
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Results:
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
||||||
@@ -631,10 +642,6 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> --- spring-boot:4.0.2:repackage <span style="color:#f92672">(</span>repackage<span style="color:#f92672">)</span> @ store ---
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> --- spring-boot:4.0.2:repackage <span style="color:#f92672">(</span>repackage<span style="color:#f92672">)</span> @ store ---
|
||||||
</span></span><span style="display:flex;"><span>...
|
</span></span><span style="display:flex;"><span>...
|
||||||
</span></span><span style="display:flex;"><span>...
|
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Installing /home/fymio/store/pom.xml to /home/fymio/.m2/repository/us/fymio/store/0.0.1-SNAPSHOT/store-0.0.1-SNAPSHOT.pom
|
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Installing /home/fymio/store/target/store-0.0.1-SNAPSHOT.jar to /home/fymio/.m2/repository/us/fymio/store/0.0.1-SNAPSHOT/store-0.0.1-SNAPSHOT.jar
|
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> ------------------------------------------------------------------------
|
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> BUILD SUCCESS
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> BUILD SUCCESS
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> ------------------------------------------------------------------------
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> ------------------------------------------------------------------------
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Total time: 14.787 s
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>INFO<span style="color:#f92672">]</span> Total time: 14.787 s
|
||||||
@@ -649,12 +656,13 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>So we can tell that our application was built without errors.</p>
|
<p>Our application built without errors.</p>
|
||||||
<h1>Dependency Management</h1><p>Dependencies are third-party libraries or frameworks we use in our application. For example to build a web application we need an embedded web server like <em>Tomcat</em>, we need libraries for handling web requests building APIs, processing JSON data, logging and so on.</p>
|
<hr>
|
||||||
<p>In spring boot applications instead of adding multiple individual libraries we can use a <strong>starter dependency</strong>.</p>
|
<h1>Dependency Management</h1><p>Dependencies are third-party libraries or frameworks we use in our application. For example, to build a web application we need an embedded web server like <em>Tomcat</em>, libraries for handling web requests, building APIs, processing JSON data, logging and so on.</p>
|
||||||
|
<p>In Spring Boot applications, instead of adding multiple individual libraries, we can use a <strong>starter dependency</strong>.</p>
|
||||||
<p><img src="assets/spring-boot-starter-web.svg" alt="Spring Boot Starter Web" loading="lazy" />
|
<p><img src="assets/spring-boot-starter-web.svg" alt="Spring Boot Starter Web" loading="lazy" />
|
||||||
<em>Img. 5 – Spring Boot Starter Web</em></p>
|
<em>Img. 5 — Spring Boot Starter Web</em></p>
|
||||||
<p>To use this dependency we just need to copy the code below to our <code>pom.xml</code> file.</p>
|
<p>To use this dependency, copy the following into your <code>pom.xml</code>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672"><dependency></span>
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672"><dependency></span>
|
||||||
@@ -671,27 +679,27 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>So the <code>dependencies</code> section would look like this</p>
|
<p>So the <code>dependencies</code> section would look like this:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672"><dependencies></span>
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672"><dependencies></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-test<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-test<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scope></span>test<span style="color:#f92672"></scope></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><scope></span>test<span style="color:#f92672"></scope></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><groupId></span>org.springframework.boot<span style="color:#f92672"></groupId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-web<span style="color:#f92672"></artifactId></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"><artifactId></span>spring-boot-starter-web<span style="color:#f92672"></artifactId></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#75715e"><!-- <version>4.1.0-M1</version> --></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e"><!-- <version>4.1.0-M1</version> --></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependency></span>
|
||||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672"></dependencies></span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span><span style="color:#f92672"></dependencies></span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
title="Copy code"
|
title="Copy code"
|
||||||
@@ -701,15 +709,24 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Notice, that I commented out the version of our dependency. That’s because it’s a better practice to let Spring Boot decide what version of the dependency to use.</p>
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-purple-200 hx:bg-purple-100 hx:text-purple-900 hx:dark:border-purple-200/30 hx:dark:bg-purple-900/30 hx:dark:text-purple-200">
|
||||||
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Important</p>
|
||||||
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>Notice that the version is commented out. It’s a better practice to let Spring Boot decide what version of the dependency to use, as it ensures compatibility across your project.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
<h1>Controllers</h1><p><strong>Spring MVC</strong> stands for <em>Model View Controller</em>.</p>
|
<h1>Controllers</h1><p><strong>Spring MVC</strong> stands for <em>Model View Controller</em>.</p>
|
||||||
<p><em>Model</em> is where our application’s data lives. It represents the business logic and is usually connected to a database or other data sources. In spring boot the model can be a simple java class.</p>
|
<ul>
|
||||||
<p><em>View</em> is what the user sees. It’s the HTML, CSS or JavaScript that’s rendered in the browser. In Spring MVC views can be static files or dynamically generated.</p>
|
<li><strong>Model</strong> is where our application’s data lives. It represents the business logic and is usually connected to a database or other data sources. In Spring Boot, the model can be a simple Java class.</li>
|
||||||
<p><em>Controller</em> is like a traffic controller. It handles incoming requests from the user, interacts with the model to get data and then tells the view what to display.</p>
|
<li><strong>View</strong> is what the user sees. It’s the HTML, CSS or JavaScript rendered in the browser. In Spring MVC, views can be static files or dynamically generated.</li>
|
||||||
<p>Let’s add a new java class called <code>HomeController</code>. It will be located at <code>src/main/java/us/fymio/store/HomeController.java</code>.</p>
|
<li><strong>Controller</strong> is like a traffic controller. It handles incoming requests from the user, interacts with the model to get data and then tells the view what to display.</li>
|
||||||
|
</ul>
|
||||||
|
<p>Let’s add a new Java class called <code>HomeController</code> at <code>src/main/java/tech/codejava/store/HomeController.java</code>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> us.fymio.store;
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HomeController</span> {}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HomeController</span> {}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -721,10 +738,10 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>To make this a controller we have to decorate it with the controller annotation. And import the <code>Controller</code> from <code>org.springframework.stereotype</code> package.</p>
|
<p>To make this a controller, decorate it with the <code>@Controller</code> annotation:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> us.fymio.store;
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
@@ -739,10 +756,10 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Let’s now add an <code>index</code> method. When we send a request to the root of our website we want this method to be called. Also we need to add another special annotation to this method.</p>
|
<p>Now let’s add an <code>index</code> method. When we send a request to the root of our website, we want this method to be called:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> us.fymio.store;
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.web.bind.annotation.RequestMapping;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -764,7 +781,7 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Now we need to create this view. We add the <code>index.html</code> at <code>src/main/resources/static/index.html</code>. For now let’s just print “Hello world!”.</p>
|
<p>Now we need to create the view. Add <code>index.html</code> at <code>src/main/resources/static/index.html</code>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="color:#75715e"><!doctype html></span>
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="color:#75715e"><!doctype html></span>
|
||||||
@@ -787,11 +804,10 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>Now let’s build our application using <code>mvn spring-boot:run</code>.</p>
|
<p>Let’s build and run our application using <code>mvn spring-boot:run</code>. From the logs:</p>
|
||||||
<p>As we can see from the logs:</p>
|
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>2026-02-19T14:55:23.948+03:00 INFO <span style="color:#ae81ff">36752</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span> main<span style="color:#f92672">]</span> o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port <span style="color:#ae81ff">8080</span> <span style="color:#f92672">(</span>http<span style="color:#f92672">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>2026-02-19T14:55:23.948+03:00 INFO <span style="color:#ae81ff">36752</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span> main<span style="color:#f92672">]</span> o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port <span style="color:#ae81ff">8080</span> <span style="color:#f92672">(</span>http<span style="color:#f92672">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
title="Copy code"
|
title="Copy code"
|
||||||
@@ -801,10 +817,11 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>It means that our app is up and running at <a href="http://localhost:8080/"target="_blank" rel="noopener">localhost:8080</a>.</p>
|
<p>Our app is up and running at <a href="http://localhost:8080/"target="_blank" rel="noopener">localhost:8080</a>.</p>
|
||||||
<p><img src="assets/hello-world.png" alt="Hello world!" loading="lazy" />
|
<p><img src="assets/hello-world.png" alt="Hello world!" loading="lazy" />
|
||||||
<em>Img. 7 – Our app is up and running!</em></p>
|
<em>Img. 7 — Our app is up and running!</em></p>
|
||||||
<h1>Configuring Application Properties</h1><p>Let’s take a look at our <code>application.properties</code> file located at <code>src/main/resources/application.properties</code>.</p>
|
<hr>
|
||||||
|
<h1>Configuring Application Properties</h1><p>Let’s take a look at <code>src/main/resources/application.properties</code>:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span><span style="color:#a6e22e">spring.application.name</span><span style="color:#f92672">=</span><span style="color:#e6db74">store</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span><span style="color:#a6e22e">spring.application.name</span><span style="color:#f92672">=</span><span style="color:#e6db74">store</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
@@ -817,11 +834,10 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>To use this property in our code we can use the <code>@Value</code> annotation.</p>
|
<p>To use this property in our code, we can use the <code>@Value</code> annotation. Let’s update <code>HomeController</code> to print the application name:</p>
|
||||||
<p>Let’s change our <code>HomeController</code> class so it prints the name of our application.</p>
|
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> us.fymio.store;
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
</span></span><span style="display:flex;"><span>
|
</span></span><span style="display:flex;"><span>
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.beans.factory.annotation.Value;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.beans.factory.annotation.Value;
|
||||||
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.stereotype.Controller;
|
||||||
@@ -848,12 +864,12 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>And as we can see after running our application there is a <code>store</code> printed out in the terminal.</p>
|
<p>After running the application, we can see <code>store</code> printed in the terminal:</p>
|
||||||
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
||||||
</span></span><span style="display:flex;"><span>2026-02-19T15:32:37.507+03:00 INFO <span style="color:#ae81ff">41536</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>nio-8080-exec-1<span style="color:#f92672">]</span> o.s.web.servlet.DispatcherServlet : Initializing Servlet <span style="color:#e6db74">'dispatcherServlet'</span>
|
</span></span><span style="display:flex;"><span>2026-02-19T15:32:37.507+03:00 INFO <span style="color:#ae81ff">41536</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>nio-8080-exec-1<span style="color:#f92672">]</span> o.s.web.servlet.DispatcherServlet : Initializing Servlet <span style="color:#e6db74">'dispatcherServlet'</span>
|
||||||
</span></span><span style="display:flex;"><span>2026-02-19T15:32:37.509+03:00 INFO <span style="color:#ae81ff">41536</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>nio-8080-exec-1<span style="color:#f92672">]</span> o.s.web.servlet.DispatcherServlet : Completed initialization in <span style="color:#ae81ff">2</span> ms
|
</span></span><span style="display:flex;"><span>2026-02-19T15:32:37.509+03:00 INFO <span style="color:#ae81ff">41536</span> --- <span style="color:#f92672">[</span>store<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>nio-8080-exec-1<span style="color:#f92672">]</span> o.s.web.servlet.DispatcherServlet : Completed initialization in <span style="color:#ae81ff">2</span> ms
|
||||||
</span></span><span style="display:flex;"><span>application name <span style="color:#f92672">=</span> store
|
</span></span><span style="display:flex;"><span>application name <span style="color:#f92672">=</span> store
|
||||||
</span></span><span style="display:flex;"><span>...</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
</span></span><span style="display:flex;"><span>...</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
<button
|
<button
|
||||||
@@ -865,9 +881,362 @@ Layer Purpose Core Handling dependency injection, managing objects Web Building
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1>Dependency injection</h1><p>Imagine we are building an E-Commerce application that handles placing orders. When the order is placed, the customer’s payment needs to be processed so order service depends on a payment service like stripe payment service. In this case we can say that order service is <em>dependent</em> or <em>coupled to</em> stripe payment service.</p>
|
<hr>
|
||||||
|
<h1>Dependency Injection</h1><p>Imagine we’re building an E-Commerce application that handles placing orders. When an order is placed, the customer’s payment needs to be processed — so <code>OrderService</code> depends on a payment service like <code>StripePaymentService</code>. We can say that <code>OrderService</code> is <em>dependent on</em> (or <em>coupled to</em>) <code>StripePaymentService</code>.</p>
|
||||||
<p><img src="assets/depends-on-coupled-to.svg" alt="Depends on/Coupled to relation" loading="lazy" />
|
<p><img src="assets/depends-on-coupled-to.svg" alt="Depends on/Coupled to relation" loading="lazy" />
|
||||||
<em>Img. 8 – Depends On/Coupled To relation.</em></p>
|
<em>Img. 8 — Depends On/Coupled To relation</em></p>
|
||||||
|
<p>Let’s talk about the issues that arise when one class is <strong>tightly coupled</strong> to another.</p>
|
||||||
|
<ol>
|
||||||
|
<li><strong>Inflexibility</strong> — <code>OrderService</code> can only use <code>StripePaymentService</code>. If tomorrow we decide to switch to a different payment provider like PayPal, we would have to modify <code>OrderService</code>. Once we change it, it has to be recompiled and retested, which could impact other classes that depend on it.</li>
|
||||||
|
<li><strong>Untestability</strong> — We cannot test <code>OrderService</code> in isolation, because <code>OrderService</code> is tightly coupled with <code>StripePaymentService</code> and we can’t test its logic separately from it.</li>
|
||||||
|
</ol>
|
||||||
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200">
|
||||||
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Note</p>
|
||||||
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>The problem here isn’t that <code>OrderService</code> <em>depends</em> on <code>StripePaymentService</code> — dependencies are normal in any application. The issue is about <em>how</em> the dependency is created and managed.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p><strong>Analogy:</strong> Think of a restaurant. A restaurant needs a chef — that’s a perfectly normal dependency. If the current chef becomes unavailable, the restaurant can hire another one.</p>
|
||||||
|
<p><img src="assets/restaurant-chef-dependency.svg" alt="Restaurant — Chef dependency" loading="lazy" />
|
||||||
|
<em>Img. X — Restaurant — Chef dependency (Normal)</em></p>
|
||||||
|
<p>Now what if we replace “chef” with a specific person: John? Our restaurant is now dependent on <em>John specifically</em>. If John becomes unavailable, we can’t replace him — the restaurant is in trouble. This is an example of <strong>tight</strong> or <strong>bad coupling</strong>.</p>
|
||||||
|
<p><img src="assets/restaurant-john-dependency.svg" alt="Restaurant — John dependency" loading="lazy" />
|
||||||
|
<em>Img. X — Restaurant — John dependency (Bad coupling)</em></p>
|
||||||
|
<p>We don’t want <code>OrderService</code> to be tightly coupled to a specific payment service like Stripe. Instead, we want it to depend on a <code>PaymentService</code> <em>interface</em>, which could be Stripe, PayPal, or any other provider. To achieve this we can use the <em>interface</em> to decouple <code>OrderService</code> from <code>StripePaymentService</code>.</p>
|
||||||
|
<p><img src="assets/payment-service-as-interface.svg" alt="Payment Service as interface" loading="lazy" />
|
||||||
|
<em>Img. X — <code>PaymentService</code> as <code>interface</code></em></p>
|
||||||
|
<p>If <code>OrderService</code> depends on a <code>PaymentService</code> interface, it doesn’t know anything about Stripe, PayPal, or any other payment provider. As long as these providers implement <code>PaymentService</code>, they can be used to handle payments — and <code>OrderService</code> won’t care which one is being used.</p>
|
||||||
|
<p><strong>Benefits:</strong></p>
|
||||||
|
<ol>
|
||||||
|
<li>If we replace <code>StripePaymentService</code> with <code>PayPalPaymentService</code>, the <code>OrderService</code> class is not affected.</li>
|
||||||
|
<li>We don’t need to modify or recompile <code>OrderService</code>.</li>
|
||||||
|
<li>We can test <code>OrderService</code> in isolation, without relying on the specific payment provider like Stripe.</li>
|
||||||
|
</ol>
|
||||||
|
<p>With this setup, we simply give <code>OrderService</code> a particular implementation of <code>PaymentService</code>. This is called <strong>dependency injection</strong> — we <em>inject</em> the dependency into a class.</p>
|
||||||
|
<p><img src="assets/dependency-injection.svg" alt="Dependency Injection example" loading="lazy" />
|
||||||
|
<em>Img. X — Dependency Injection example</em></p>
|
||||||
|
<p>Let’s see how it works in our project. Create <code>OrderService</code> at <code>src/main/java/tech/codejava/store/OrderService.java</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OrderService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">placeOrder</span>() {}
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200">
|
||||||
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Note</p>
|
||||||
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>In a real project we would need to provide something like <code>Order order</code> to this method, but for teaching purposes we won’t do that.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Now create <code>StripePaymentService</code> in the same directory:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StripePaymentService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">processPayment</span>(<span style="color:#66d9ef">double</span> amount) {
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"=== STRIPE ==="</span>);
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"amount: "</span> <span style="color:#f92672">+</span> amount);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Let’s implement <code>placeOrder</code> in <code>OrderService</code> using <code>StripePaymentService</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OrderService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">placeOrder</span>() {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> paymentService <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> StripePaymentService();
|
||||||
|
</span></span><span style="display:flex;"><span> paymentService.<span style="color:#a6e22e">processPayment</span>(10);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-purple-200 hx:bg-purple-100 hx:text-purple-900 hx:dark:border-purple-200/30 hx:dark:bg-purple-900/30 hx:dark:text-purple-200">
|
||||||
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Important</p>
|
||||||
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>This is our <em>before</em> setup — before we introduced the interface. In this implementation, <code>OrderService</code> is <strong>tightly coupled</strong> to <code>StripePaymentService</code>. We cannot test <code>OrderService</code> in isolation, and switching to another payment provider would require modifying <code>OrderService</code>.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Let’s fix this. Create a <code>PaymentService</code> interface in the same directory:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">PaymentService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">processPayment</span>(<span style="color:#66d9ef">double</span> amount);
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Modify <code>StripePaymentService</code> to implement <code>PaymentService</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StripePaymentService</span> <span style="color:#66d9ef">implements</span> PaymentService {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">@Override</span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">processPayment</span>(<span style="color:#66d9ef">double</span> amount) {
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"=== STRIPE ==="</span>);
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"amount: "</span> <span style="color:#f92672">+</span> amount);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>The recommended way to inject a dependency into a class is via its <strong>constructor</strong>. Let’s define one in <code>OrderService</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OrderService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> PaymentService paymentService;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">OrderService</span>(PaymentService paymentService) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">paymentService</span> <span style="color:#f92672">=</span> paymentService;
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">placeOrder</span>() {
|
||||||
|
</span></span><span style="display:flex;"><span> paymentService.<span style="color:#a6e22e">processPayment</span>(10);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Now let’s see this in action. Modify <code>StoreApplication</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.SpringApplication;
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@SpringBootApplication</span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StoreApplication</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// SpringApplication.run(StoreApplication.class, args);</span>
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> orderService <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> OrderService(<span style="color:#66d9ef">new</span> StripePaymentService());
|
||||||
|
</span></span><span style="display:flex;"><span> orderService.<span style="color:#a6e22e">placeOrder</span>();
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Running the application <em>(output intentionally reduced)</em>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">===</span> STRIPE <span style="color:#f92672">===</span>
|
||||||
|
</span></span><span style="display:flex;"><span>amount: 10.0
|
||||||
|
</span></span><span style="display:flex;"><span>...</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Now let’s create a <code>PayPalPaymentService</code> in the same directory:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PayPalPaymentService</span> <span style="color:#66d9ef">implements</span> PaymentService {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">@Override</span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">processPayment</span>(<span style="color:#66d9ef">double</span> amount) {
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"=== PayPal ==="</span>);
|
||||||
|
</span></span><span style="display:flex;"><span> System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">"amount: "</span> <span style="color:#f92672">+</span> amount);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Now we can switch from <code>StripePaymentService</code> to <code>PayPalPaymentService</code> in <code>StoreApplication</code> — without touching <code>OrderService</code> at all:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.SpringApplication;
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@SpringBootApplication</span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StoreApplication</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// SpringApplication.run(StoreApplication.class, args);</span>
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// var orderService = new OrderService(new StripePaymentService());</span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> orderService <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> OrderService(<span style="color:#66d9ef">new</span> PayPalPaymentService());
|
||||||
|
</span></span><span style="display:flex;"><span> orderService.<span style="color:#a6e22e">placeOrder</span>();
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>...
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">===</span> PayPal <span style="color:#f92672">===</span>
|
||||||
|
</span></span><span style="display:flex;"><span>amount: 10.0
|
||||||
|
</span></span><span style="display:flex;"><span>...</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Notice that we didn’t change <code>OrderService</code>. In <em>object-oriented programming</em> this is known as the <strong>Open/Closed Principle</strong>:</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>A class should be open for extension and closed for modification.</p>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
<p>In other words: we should be able to add new functionality to a class without changing its existing code. This reduces the risk of introducing bugs and breaking other parts of the application.</p>
|
||||||
|
<hr>
|
||||||
|
<h2>Setter Injection<span class="hx:absolute hx:-mt-20" id="setter-injection"></span>
|
||||||
|
<a href="#setter-injection" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Another way to inject a dependency is via a <strong>setter</strong>. In <code>OrderService</code>, let’s define one:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OrderService</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span> PaymentService paymentService;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">setPaymentService</span>(PaymentService paymentService) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">paymentService</span> <span style="color:#f92672">=</span> paymentService;
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">OrderService</span>(PaymentService paymentService) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">paymentService</span> <span style="color:#f92672">=</span> paymentService;
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">placeOrder</span>() {
|
||||||
|
</span></span><span style="display:flex;"><span> paymentService.<span style="color:#a6e22e">processPayment</span>(10);
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>We can use it like this in <code>StoreApplication</code>:</p>
|
||||||
|
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
|
||||||
|
|
||||||
|
<div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.codejava.store;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.SpringApplication;
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@SpringBootApplication</span>
|
||||||
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StoreApplication</span> {
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// SpringApplication.run(StoreApplication.class, args);</span>
|
||||||
|
</span></span><span style="display:flex;"><span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// var orderService = new OrderService(new StripePaymentService());</span>
|
||||||
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">var</span> orderService <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> OrderService(<span style="color:#66d9ef">new</span> PayPalPaymentService());
|
||||||
|
</span></span><span style="display:flex;"><span> orderService.<span style="color:#a6e22e">setPaymentService</span>(<span style="color:#66d9ef">new</span> PayPalPaymentService());
|
||||||
|
</span></span><span style="display:flex;"><span> orderService.<span style="color:#a6e22e">placeOrder</span>();
|
||||||
|
</span></span><span style="display:flex;"><span> }
|
||||||
|
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
|
||||||
|
<button
|
||||||
|
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
|
||||||
|
title="Copy code"
|
||||||
|
>
|
||||||
|
<div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-purple-200 hx:bg-purple-100 hx:text-purple-900 hx:dark:border-purple-200/30 hx:dark:bg-purple-900/30 hx:dark:text-purple-200">
|
||||||
|
<p class="hx:flex hx:items-center hx:font-medium"><svg height=16px class="hx:inline-block hx:align-middle hx:mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>Important</p>
|
||||||
|
|
||||||
|
<div class="hx:w-full hx:min-w-0 hx:leading-7">
|
||||||
|
<div class="hx:mt-6 hx:leading-7 hx:first:mt-0"><p>If you remove the constructor from <code>OrderService</code> and forget to call the setter, the application will crash with a <code>NullPointerException</code>. Use setter injection only for <strong>optional</strong> dependencies — ones that <code>OrderService</code> can function without.</p></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="hx:mt-16"></div>
|
<div class="hx:mt-16"></div>
|
||||||
|
|||||||