package com.example.demo.dto;
import com.example.demo.validation.UniqueEmail;
import jakarta.validation.constraints.*;
import lombok.Data;
@Data
public class CreateUserRequest {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Invalid email format")
@UniqueEmail
private String email;
@Pattern(regexp = "^\+?[1-9]\d{1,14}$", message = "Invalid phone number")
private String phone;
@Min(value = 18, message = "Must be at least 18 years old")
@Max(value = 120, message = "Age cannot exceed 120")
private Integer age;
@AssertTrue(message = "Must accept terms and conditions")
private Boolean termsAccepted;
}
package com.example.demo.validation;
import com.example.demo.repository.UserRepository;
import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
public @interface UniqueEmail {
String message() default "Email already exists";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
private final UserRepository userRepository;
public UniqueEmailValidator(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
if (email == null) {
return true; // Let @NotNull handle null validation
}
return !userRepository.existsByEmail(email);
}
}
package com.example.demo.controller;
import com.example.demo.dto.CreateUserRequest;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
@Validated
public class ValidationController {
private final UserService userService;
public ValidationController(UserService userService) {
this.userService = userService;
}
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
User user = new User();
user.setName(request.getName());
user.setEmail(request.getEmail());
user.setPhone(request.getPhone());
User created = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
@GetMapping("/validate")
public ResponseEntity<String> validateParam(
@RequestParam @Email(message = "Invalid email format") String email
) {
return ResponseEntity.ok("Valid email: " + email);
}
}
Bean Validation (JSR 380) validates objects using annotations. Common constraints include @NotNull, @NotBlank, @Size, @Email, @Min, @Max, and @Pattern. I apply annotations to fields, methods, or parameters. @Valid triggers validation in Spring controllers. Custom validators extend ConstraintValidator for business rules. Groups enable conditional validation. ConstraintViolation contains error details. Validation happens before data reaches service layer, ensuring data integrity. Spring's @Validated supports method-level validation in services. Error messages are customizable via properties files or annotation parameters. Validation prevents invalid data from persisting, reducing bugs and improving security. The declarative approach keeps validation logic close to domain models.
Related snips
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: String!
GraphQL API with Spring Boot
class SignupForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :account_name, :string
attribute :email, :string
Shallow Controller, Deep Params: Form Object Pattern
package com.example.starter.config;
import com.example.starter.properties.CustomProperties;
import com.example.starter.service.CustomService;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
Custom Spring Boot starters
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Form Validation Example</title>
<style>
HTML forms with validation and accessibility
package com.example.demo.config;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
Messaging with Apache Kafka
import axios from 'axios';
export type NormalizedErrors = {
fields: Record<string, string>;
formLevel: string | null;
};
Frontend: normalize and display server validation errors
Share this code
Here's the card — post it anywhere.