How Controller, Service Layer, and DAO Layer works in Spring Boot? | Introduction.

Flow: Controller → Service Layer → DAO Layer →Database

Note: We are not adding data to the database, we are just going to understand the flow.

Controller

Create a package controller.

Add class: UserController.java

UserController.java

To declare class as REST API, annotate class with @RestController

//calling first REST API

@RestController

public class UserController {

//to call PostServiceImpl() method we need to create object of parent i.e PostService.java

@Autowired

private PostService postService;

@GetMapping(“/test”)

public String test() {

return “api is working fine”;

}

}

→ Testing APIs with Postman client.

test api

To understand better let’s take the example where the user is going to add the posts.

Let’s deep dive into the Controller, Service layer, and DAO layer.

Controller

UserController.java

package com.restapi.example.controller;

import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

public class UserController {

@GetMapping(“/test”)

public String test() {

return “api is working fine”;

}

//Creating method to get all posts

@GetMapping(“/posts”)

public List<Post> getPosts(){

//controller cannot get all the posts themselves, so he will request a service layer to give posts.

}

}

@GetMapping(“/posts”): we want GET request to return all the posts, so we have used @GetMapping.

→ Firstly, create a Post.java class in a model package with id, title, and content fields.

2. Create model/entities package

Let’s make another package: model and class Post.java

Post.java

→ Now our post will have an id, title, and content.

//adding fields with private datatype

private int id;

private String title;

private String content;

→ Add constructors, getters, and setters and override toString() method.

→ Adding class: Post.java

Post.java

package com.restapi.example.model;

public class Post {

//adding fields

private int id;

private String title;

private String content;

//adding super constructor

public Post() {

super();

// TODO Auto-generated constructor stub

}

//adding parameterized constructor

public Post(int id, String title, String content) {

super();

this.id = id;

this.title = title;

this.content = content;

}

//adding getters and setters

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public String getContent() {

return content;

}

public void setContent(String content) {

this.content = content;

}

//adding to toString() method

@Override

public String toString() {

return “Post [id=” + id + “, title=” + title + “, content=” + content + “]”;

}

}

Second, we need to create a getPost() method and the post will have id, title, and content fields, so let’s create a model or entity like below.

Here, we are going to create a list of posts, which will return all the posts.

3. Service Layer

A controller cannot do all the tasks as he is only responsible to take requests, so the controller will pass the request to the service layer.

Let’s create an interface in with new package ‘service’

Adding interface and class

1. PostService.java (interface)

2. PostServiceImpl.java (class)

In PostService.java it will contain the only name of the method (not body) which we have defined in the controller i.e Controller.java.

PostService.java

package com.restapi.example.service;

import java.util.List;

import com.restapi.example.model.Post;

public interface PostService {

public List<Post> getPosts();

}

We will create a class to implement the body of the getPosts() defined in PostService.java

PostServiceImpl.java

package com.restapi.example.service;

import java.util.ArrayList;

import java.util.List;

import org.springframework.stereotype.Service;

import com.restapi.example.model.Post;

@Service

public class PostServiceImpl implements PostService {

//storing data temporary…

List<Post> list;

//adding constructor of List<Post>

public PostServiceImpl() {

// adding data into this constructor.

list = new ArrayList<>();

list.add(new Post(1, “first post”, “Hey, this is my first post”));

list.add(new Post(2, “second post”, “Hey,this is my second post”));

}

@Override

public List<Post> getPosts() {

// TODO Auto-generated method stub

return list;

}

}

→This will help to achieve loose coupling.

→ @Service is annotated on class PostServiceImpl.java to say spring boot, this is my Service Layer.

Now we are done with the most important steps, we now just need to call the getPosts().

To call getPosts() which is defined in PostServiceImpl.java we need to create the object of PostService.java.

→To create an object we tell spring boot, hey please create the object for me, for this we will Autowire concept.

@AutoWired annotation will create an object automatically, so we do not need to use the ‘new’ keyword to create an object. Thus helping us achieve loose coupling.

→ We will declare an interface type variable of the parent, here PostService.java is the parent for PostServiceImpl.java (child class)

Note: PostService.java is an interface

e.g private PostService postService;

(you can declare private or public it totally depends on you).

UserController.java

package com.restapi.example.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import com.restapi.example.model.Post;

import com.restapi.example.service.PostService;

@RestController

public class UserController {

//to call PostServiceImpl() method we need to create object of parent i.e PostService.java

@Autowired

private PostService postService;

@GetMapping(“/test”)

public String test() {

return “api is working fine”;

}

//get all posts

@GetMapping(“/posts”)

public List<Post> getPosts(){

//calling child class getPosts() method of PostServiceImpl using postService(parent).

return this.postService.getPosts();

}

}

Q. How Autowiring will work?

@Autowired

private PostService postService;

→For the interface PostService.java which has the implementation class PostServiceImpl.java, using AutoWired it will create an object of implementation class PostServiceImpl.java and it will inject into postService according to the rule of the dependency injection.

So we will get the object for free, just by using annotation @AutoWired.

Once the object is created we can call that object very easily.

return this.postService.getPosts();

Testing with Postman

Conclusion: In this way, the first controller will receive the request at first then the controller will pass the request to the Service Layer. Now Service Layer will pass the request to the DAO layer for saving the data.

Software Engineer at HCL | Technical Content Writing | Follow me on LinkedIn https://www.linkedin.com/in/sagarkudu/