Quiz: Service Layer and Architecture
Test your knowledge on the service layer, validation, and MVC architecture.
30 questions - Click on each question to reveal the answer.
Questions 1-10: Service Layer
Question 1: What is the role of the Service layer in the MVC architecture?
Answer: The Service layer contains the application's business logic. It:
- Orchestrates operations between controllers and repositories
- Applies business rules
- Manages transactions
- Is independent of the HTTP protocol
Question 2: Which annotation is used to declare a Spring service?
Answer: @Service - It is a specialized stereotype of @Component indicating that the class contains business logic.
@Service
public class UserService {
// business logic
}
Question 3: Why not put business logic in the controller?
Answer: Separating business logic from the controller allows:
- Reusability: the service can be called by multiple controllers
- Testability: test logic without HTTP
- Maintainability: more organized code
- Separation of concerns: each layer has a specific role
Question 4: How to inject a Repository into a Service?
Answer: By constructor injection (recommended):
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Question 5: What is a DTO (Data Transfer Object)?
Answer: A DTO is a simple object used to transfer data between layers. It:
- Contains no business logic
- Exposes only necessary data
- Protects the JPA entity from direct exposure
- Allows data formatting for the API
Question 6: Why use DTOs instead of JPA entities directly?
Answer:
- Security: do not expose sensitive fields (password)
- Performance: avoid lazy loading of relationships
- Flexibility: different format from the entity
- Decoupling: internal changes do not affect the API
- Validation: specific input/output rules
Question 7: How to convert an entity to a DTO?
Answer: Several approaches:
// 1. Manual method
public UserDto toDto(User user) {
return new UserDto(user.getId(), user.getName(), user.getEmail());
}
// 2. With MapStruct
@Mapper
public interface UserMapper {
UserDto toDto(User user);
}
// 3. With ModelMapper
modelMapper.map(user, UserDto.class);
Question 8: What is the difference between a RequestDTO and a ResponseDTO?
Answer:
- RequestDTO: incoming data (creation, update), contains validation
- ResponseDTO: outgoing data, formatted for the client
// Request
public class CreateUserRequest {
@NotBlank
private String email;
@Size(min = 8)
private String password;
}
// Response
public class UserResponse {
private Long id;
private String email;
// No password!
}
Question 9: How to handle errors in the Service layer?
Answer: Throw custom exceptions:
@Service
public class UserService {
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found: " + id));
}
}
These exceptions are then handled by @ControllerAdvice.
Question 10: What is @Transactional on a service?
Answer: @Transactional automatically manages transactions:
- Starts a transaction at the beginning of the method
- Commits if successful
- Rolls back if an exception occurs
@Service
@Transactional
public class OrderService {
// All methods are transactional
}
Questions 11-20: Validation
Question 11: What dependency to add for validation?
Answer: spring-boot-starter-validation
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Question 12: How to enable validation on a controller?
Answer: With @Valid or @Validated on the parameter:
@PostMapping
public ResponseEntity<User> create(@Valid @RequestBody CreateUserRequest request) {
// If validation fails, MethodArgumentNotValidException is thrown
}
Question 13: What are common validation annotations?
Answer:
| Annotation | Description |
|---|---|
@NotNull | Must not be null |
@NotBlank | Not null, not empty, not whitespace |
@NotEmpty | Not null and not empty |
@Size(min, max) | Size between min and max |
@Min, @Max | Numeric min/max value |
@Email | Valid email format |
@Pattern | Custom regex |
@Past, @Future | Date in the past/future |
Question 14: How to customize the validation error message?
Answer: With the message attribute:
public class CreateUserRequest {
@NotBlank(message = "Email is required")
@Email(message = "Invalid email format")
private String email;
@Size(min = 8, message = "Password must be at least 8 characters")
private String password;
}
Question 15: How to create a custom validation?
Answer: Create an annotation and a validator:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
public @interface UniqueEmail {
String message() default "Email already used";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
// Check if email exists
}
}
Question 16: What is the difference between @Valid and @Validated?
Answer:
@Valid: standard Java (JSR-380), cascades validation@Validated: Spring, supports validation groups
// Validation groups
public interface OnCreate {}
public interface OnUpdate {}
@NotNull(groups = OnUpdate.class)
private Long id;
@Validated(OnCreate.class)
public void create(...) { }
Question 17: How to validate query parameters?
Answer: Add @Validated on the controller:
@RestController
@Validated
public class UserController {
@GetMapping("/users")
public List<User> search(
@RequestParam @Min(0) int page,
@RequestParam @Max(100) int size) {
// ...
}
}
Question 18: How to validate a nested object?
Answer: Use @Valid on the nested field:
public class OrderRequest {
@Valid // Cascades validation
@NotNull
private AddressDto shippingAddress;
}
public class AddressDto {
@NotBlank
private String street;
@NotBlank
private String city;
}
Question 19: How to retrieve validation errors?
Answer: Via BindingResult or @ExceptionHandler:
// Option 1: BindingResult
@PostMapping
public ResponseEntity<?> create(@Valid @RequestBody Request req, BindingResult result) {
if (result.hasErrors()) {
return ResponseEntity.badRequest().body(result.getAllErrors());
}
}
// Option 2: ControllerAdvice (recommended)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidation(MethodArgumentNotValidException ex) {
// Extract errors
}
Question 20: What is service-level validation?
Answer: Validation of business logic (not just format):
@Service
public class OrderService {
public Order createOrder(OrderRequest request) {
// Business validation
if (request.getQuantity() > productService.getStock(request.getProductId())) {
throw new InsufficientStockException("Insufficient stock");
}
// ...
}
}
Questions 21-30: Architecture
Question 21: What are the 3 main layers of the MVC architecture?
Answer:
- Controller (Presentation): handles HTTP, input validation
- Service (Business): business logic, transactions
- Repository (Data): database access
Client → Controller → Service → Repository → Database
Question 22: In which layer should transaction management be placed?
Answer: In the Service layer. This is where the business logic that defines what constitutes an atomic unit of work is located.
@Service
@Transactional
public class TransferService {
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// The entire operation is atomic
}
}
Question 23: How to organize packages in a Spring Boot project?
Answer: By layer or by feature:
// By layer
com.example.app
├── controller/
├── service/
├── repository/
├── model/
└── dto/
// By feature (recommended for large projects)
com.example.app
├── user/
│ ├── UserController
│ ├── UserService
│ └── UserRepository
├── order/
└── product/
Question 24: What is the Single Responsibility Principle (SRP)?
Answer: A class should have only one reason to change. Each class has a single responsibility:
- Controller: handle HTTP requests
- Service: business logic
- Repository: data access
Bad example: a controller that does everything (HTTP + business + DB).
Question 25: Why use interfaces for services?
Answer:
- Decoupling: clients depend on the abstraction
- Testability: easy to mock
- Flexibility: change implementation
- Proxying: Spring AOP works better
public interface UserService {
User findById(Long id);
}
@Service
public class UserServiceImpl implements UserService { }
Question 26: What is a @ControllerAdvice?
Answer: A component that handles exceptions globally for all controllers:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(UserNotFoundException ex) {
return ResponseEntity.status(404).body(new ErrorResponse(ex.getMessage()));
}
}
Question 27: How to structure a standard error response?
Answer: Create a consistent error DTO:
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
}
// Or ProblemDetail format (RFC 7807)
Question 28: What is the difference between @RestController and @Controller?
Answer:
@Controller: returns views (HTML)@RestController: returns data (JSON/XML)
@RestController = @Controller + @ResponseBody
@RestController // Everything is JSON
public class UserController { }
@Controller
public class ViewController {
@GetMapping("/")
public String home() {
return "index"; // Thymeleaf view
}
}
Question 29: How to handle appropriate HTTP codes?
Answer: Use ResponseEntity:
@PostMapping
public ResponseEntity<User> create(@RequestBody UserRequest req) {
User user = userService.create(req);
return ResponseEntity
.status(HttpStatus.CREATED) // 201
.body(user);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204
}
Question 30: What are common HTTP codes in REST?
Answer:
| Code | Meaning | Usage |
|---|---|---|
| 200 | OK | Successful GET, PUT |
| 201 | Created | Successful POST |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Validation failed |
| 401 | Unauthorized | Not authenticated |
| 403 | Forbidden | Not authorized |
| 404 | Not Found | Resource not found |
| 500 | Server Error | Internal error |
Score
| Score | Level |
|---|---|
| 27-30 | Excellent - Mastered architecture |
| 21-26 | Good - Some revisions needed |
| 15-20 | Average - Review the chapters |
| Less than 15 | Needs improvement - Go back to basics |