Basic Spring Boot Project Architecture
Table of contents
No headings in the article.
Spring boot is a java-based framework that has been introduced in 2014 as part of the Spring framework eco-system. It is designed to quickly develop and deliver production-grade applications. It introduced many features like auto-configuration, embedded Tomcat and the layer of abstraction that reduces the amount of boilerplate code. It is very easy to learn and get used to for both beginners and experienced java developers.
In this article, we're going to have a brief look at a simple Spring Boot application to give you some idea of how easy it is to start developing an application as quickly and painlessly as possible.
To start, let's list down the common components of a Spring Boot project such as the one we'll be working on. A Spring Boot project is usually divided into modules or layers as follows:
The controller layer
The service layer
the repository or Data Access Layer
The model or domain layer
The configuration layer
Let's talk more about each layer:
The controller
The controller is a java class where we define our APIs. It is the first point of contact with the client where it's responsible for handling HTTP requests (GET, POST, PUT, DELETE). If the client sends a get request to fetch some resource from the database, the controller will send that request to the service layer, which sends it to the data access layer to fetch it from the database.
The service
This is where we define our business logic. This class transfers requests and data between the controller and DAO layer and performs operations, if required, on those data.
The DAO or repository
The DAO or Data Access Object is an interface responsible for persisting and retrieving data from the database based on the type of request received from the service layer. When Spring Data JPA is integrated into a Spring Boot project, our DAO interface can extend one of Spring Data JPA's interfaces which contains a number of common useful database operations like create, retrieve, update and delete. Examples of those repositories include JPARepository, CrudRepository and PagingAndSortingRepository.
The model/ domain layer
Models are java objects that represent the data transferred between the application and the client. We can map a model to a table in a relational database typically using an ORM tool like Hibernate where each property of the model corresponds to a column of that table. In the context of relational mapping, we can refer to the model class as an entity.
The configuration layer
Spring Boot provides different ways to define configuration settings for database, security and any configuration required to set up an application. The most common ways are using application.properties or application.yaml file and Java configuration classes
Now let's create these classes and their packages step by step.
First, We'll start with the
application.properties
file, which is provided by Spring Boot by default in the /src/main/resources directory. We'll declare database properties to connect to postgresql database as bellow. You can use any database of your choice.spring.datasource.driverClassName=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5432/user spring.datasource.username=postgres spring.datasource.password=postgres
As you can see above, we declared the database Driver, url, username and password.
Now once we run the application, it will connect to postgres with these credentials.
Next, create the following packages under src/main/java: controller, service, repository and model or entity
Now we can start with the model. Inside the /model or /entity package, create a class and call it
User
and define your fields, constructors, getters and setters. If you're using Spring Data JPA, you may add the relevant annotations@Entity @Table(name = "user") public class User { @Id private Integer id; private String userName; private String password; // constructors // getters and setters
@Entity
and@Table
denote the object that will be mapped to the respective database table.@Id
is used on top of the id field that represents the primary key of the entity.
As a next step, let's create the DAO layer, which will be an interface inside the /repository package and will extend JpaRepository provided by Spring Data JPA.
@Repository public class UserRepository extends JpaRepository<User, Integer> { }
@Repository
is a specialized form of Spring's@Component
annotation to denote the repository.Notice that JpaRepository has two parameters: Entity type and primary key type of that entity
Next, we'll create a service class inside the /service package and then autowire our UserRepository and define some methods that invoke methods from that repository.
@Service public public UserService { @Autowired private UserRepository userRepository; public List<User> findUsers() { return userRepository.findAll(); } public User findUserById(Integer id) { return userRepository.findById(id).orElse(null); } public User saveUser(User user) { return userRepository.save(user); } public User updateUserById(Integer id, User user) { User updatedUser = userRepository.findById(id).orElse(null); updatedUser.save(user); return updatedUser; } public void deleteUserById(Integer id) { User user = userRepository.findById(id).orElse(null); userRepository.delete(user); } }
Lastly, let's create a controller class inside the /controller package.
@RestController @RequiredMapping("/user") public class UserRestController { @Autowired private UserService userService; @GetMapping public List<User> getUsers() { return userService.findUsers(); } @GetMapping("/{id}") public User getUserById(@PathVariable Integer id) { return userService.findUserById(id); } @PostMapping public User postUser(@RequestBody User user) { return userService.saveUser(user); } @PutMapping("/{id}") public User putUser(@PathVariable Integer id, @RequestBody User user) { return userService.updateUserById(id, user); } @DeleteMapping(/"{id}") public String deleteUser(@PathVariable Integer id) { userService.deleteUser(id); return "user has been deleted successfully"; } }
The @RestController annotation indicates this class will be handling web requests
Here, we're injecting our UserService into the controller and creating API methods that invoke each service method.
All
@GetMapping
,@PostMapping
,@DeleteMapping
and@PutMapping
annotations are used to map HTTP requests to the appropriate handler methods.@PathVariable
is used to bind a method parameter to the path variable. In theGET
request in our example, theid
passed in the url will be extracted and passed to the method as a parameter to query the database for a record with that id.@RequestBody
binds the JSON payload or request body of an HTTP request to a method argument, which is usually a java object.
Once you run the application, you can use a tool like postman to test each request using the proper endpoints. The endpoint of POST
request would be http://localhost:8080/user
and the JSON request will look something like this
{
"id": 1,
"userName": "user",
"password": "test@123"
}
Once you send the above request, a record should be saved to the database. To fetch that record, you can send a request using the same url but as a GET
request.
You can learn more about Spring Boot in detail by going through Spring's guide here https://spring.io/guides/gs/spring-boot/
or Baeldung's blogs here https://www.baeldung.com/spring-boot