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

Flow: Controller → Service Layer → DAO Layer →Database

Sagar Kudu
5 min readJan 6, 2021

In this example, you will get an end-to-end complete understanding of the controller, service layer, and DAO layer works in spring boot.

Controller

Create a package controller and add the class: UserController.java.

UserController.java

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

//calling first REST API

@RestController
public class UserController {
//to call PostServiceImpl() method we need to create an object of the parent i.e PostService.java

@Autowired
private PostService postService;
@GetMapping("/test")
public String test() {
return "api is working fine";
}
}

→ Testing APIs with Postman client.
Note: We are not adding data to the database, we are just going to understand the flow.

Testing 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 a 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 a 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 with the new package called → ‘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 the body) that 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 Posts API with Postman

Conclusion: In this way, the first controller will receive the request 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.

--

--

Sagar Kudu

I am Full Stack Java Developer @ Tata Strive | Get blogs and tutorials related to the (React | Kafka | DevOps) | Connect https://www.linkedin.com/in/sagarkudu/