The service layer helps organize your code by keeping business logic separate from other parts. It makes your app easier to understand and change.
Why service layer matters in Spring Boot
Start learning this pattern below
Jump into concepts and practice - no test required
public interface UserService {
User findUserById(Long id);
void createUser(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
public User findUserById(Long id) {
// business logic here
return userRepository.findById(id).orElse(null);
}
@Override
public void createUser(User user) {
// business logic here
userRepository.save(user);
}
}The service layer is usually an interface and a class implementing it.
Use @Service annotation to mark service classes in Spring Boot.
public interface OrderService {
void placeOrder(Order order);
}
@Service
public class OrderServiceImpl implements OrderService {
@Override
public void placeOrder(Order order) {
// business logic to place order
}
}@Service public class ProductService { public List<Product> getAvailableProducts() { // business logic to filter available products return List.of(); } }
This example shows a service that holds greeting messages and a controller that uses it. The service keeps the greeting logic separate from the controller, making the code cleaner and easier to maintain.
package com.example.demo.service; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; @Service public class GreetingService { private final Map<String, String> greetings = new HashMap<>(); public GreetingService() { greetings.put("en", "Hello"); greetings.put("es", "Hola"); greetings.put("fr", "Bonjour"); } public String greet(String lang, String name) { String greetWord = greetings.getOrDefault(lang, "Hello"); return greetWord + ", " + name + "!"; } } // Usage in a controller package com.example.demo.controller; import com.example.demo.service.GreetingService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class GreetingController { private final GreetingService greetingService; public GreetingController(GreetingService greetingService) { this.greetingService = greetingService; } @GetMapping("/greet") public String greetUser(@RequestParam String lang, @RequestParam String name) { return greetingService.greet(lang, name); } }
Keeping business logic in the service layer helps when you want to change rules without touching controllers or repositories.
Service layer makes unit testing easier because you can test business logic separately.
Controllers should focus on handling web requests, not business rules.
The service layer separates business logic from other parts of the app.
It makes code easier to read, test, and maintain.
Use @Service classes in Spring Boot to create this layer.
Practice
Solution
Step 1: Understand the role of service layer
The service layer contains business logic and acts as a bridge between controllers and repositories.Step 2: Identify incorrect roles
Handling database connections is the repository's job, and UI rendering is done by the view layer, not the service layer.Final Answer:
It separates business logic from controllers and repositories. -> Option BQuick Check:
Service layer = business logic separation [OK]
- Confusing service layer with repository layer
- Thinking service layer handles UI rendering
- Assuming service layer manages database connections
Solution
Step 1: Recall Spring stereotypes
@Service is the annotation used to mark service layer classes in Spring Boot.Step 2: Differentiate other annotations
@Repository is for data access, @Controller for web controllers, and @ComponentScan is for scanning components, not marking services.Final Answer:
@Service -> Option AQuick Check:
@Service marks service classes [OK]
- Using @Repository instead of @Service
- Confusing @Controller with service annotation
- Mistaking @ComponentScan as a service marker
getDiscountedPrice(100)?
public double getDiscountedPrice(double price) {
if (price > 50) {
return price * 0.9;
}
return price;
}Solution
Step 1: Analyze the input and condition
The input price is 100, which is greater than 50, so the if condition is true.Step 2: Calculate the discounted price
Price * 0.9 = 100 * 0.9 = 90.0Final Answer:
90.0 -> Option AQuick Check:
Price > 50 applies 10% discount [OK]
- Returning original price without discount
- Confusing multiplication factor
- Misreading the condition operator
@Service
public class UserService {
public void saveUser(User user) {
userRepository.save(user);
}
}Solution
Step 1: Check dependency injection
The userRepository is used but not injected or declared, so it needs @Autowired or constructor injection.Step 2: Verify annotations and method signature
@Service is correct for service classes; saveUser can be void; User class is valid here.Final Answer:
Missing @Autowired for userRepository injection. -> Option CQuick Check:
Dependencies must be injected in service [OK]
- Forgetting to inject repository
- Changing service annotation incorrectly
- Expecting return value unnecessarily
Solution
Step 1: Understand separation of concerns
Controllers handle web requests, repositories handle data access, so business logic like logging and transactions belong in the service layer.Step 2: Apply best practices for maintainability
Service layer is the right place to add cross-cutting concerns like logging and transaction management to keep code clean and reusable.Final Answer:
Inside the service layer methods -> Option DQuick Check:
Logging and transactions belong in service layer [OK]
- Adding business logic in controllers
- Mixing transactions in repositories
- Placing logic in main application class
