{"id":138382,"date":"2025-10-27T18:00:00","date_gmt":"2025-10-27T16:00:00","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=138382"},"modified":"2025-10-27T12:52:53","modified_gmt":"2025-10-27T10:52:53","slug":"developing-stateful-custom-bean-validation-using-spring-boot","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html","title":{"rendered":"Developing Stateful Custom Bean Validation Using Spring Boot"},"content":{"rendered":"<p>Bean Validation is a core feature of Spring Boot used to enforce rules on Java objects before they are processed or persisted. While basic validations like <code>@NotNull<\/code> or <code>@Email<\/code> cover most cases, real-world applications often need custom and stateful validations \u2014 where validation logic depends on multiple fields, external configurations, or even runtime data. Let us delve into understanding spring custom stateful bean validation and how it can enhance data integrity in your applications.<\/p>\n<h2><a name=\"section-1\"><\/a>1. What is Bean Validation in Spring Boot?<\/h2>\n<p>Bean Validation is a specification defined under <a href=\"https:\/\/beanvalidation.org\/2.0\/\" target=\"_blank\" rel=\"noopener noreferrer\">JSR 380 (Jakarta Bean Validation 2.0)<\/a>. It provides a unified way to apply validation rules directly to the fields of Java objects using annotations. Spring Boot integrates seamlessly with this validation framework via the <a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/htmlsingle\/#boot-features-validation\" target=\"_blank\" rel=\"noopener noreferrer\"><code>spring-boot-starter-validation<\/code><\/a> dependency, which internally uses <a href=\"https:\/\/hibernate.org\/validator\/\" target=\"_blank\" rel=\"noopener noreferrer\">Hibernate Validator<\/a> as the default implementation.<\/p>\n<p>With Bean Validation, you can enforce constraints on your domain models, DTOs, and request payloads without writing explicit validation logic in controllers. When a request is made, Spring automatically invokes these constraints before method execution, ensuring that only valid data reaches your business layer.<\/p>\n<h3>1.1 Common Validation Annotations<\/h3>\n<p>Here are some frequently used built-in validation annotations provided by the <a href=\"https:\/\/jakarta.ee\/specifications\/bean-validation\/2.0\/\" target=\"_blank\" rel=\"noopener noreferrer\">Jakarta Bean Validation API<\/a>:<\/p>\n<ul>\n<li><code>@NotNull<\/code> \u2013 Ensures a field is not <code>null<\/code>. Useful for mandatory fields.<\/li>\n<li><code>@Size(min, max)<\/code> \u2013 Validates that a string, array, or collection has a length or size within the specified bounds.<\/li>\n<li><code>@Email<\/code> \u2013 Checks whether a string is in a valid email format.<\/li>\n<li><code>@Pattern(regexp)<\/code> \u2013 Validates that a string matches a specified regular expression.<\/li>\n<li><code>@Min<\/code> and <code>@Max<\/code> \u2013 Validate numeric ranges for integer or decimal fields.<\/li>\n<li><code>@Past<\/code> and <code>@Future<\/code> \u2013 Ensure date or time values are in the past or future respectively.<\/li>\n<\/ul>\n<h2><a name=\"section-2\"><\/a>2. Code Example<\/h2>\n<p>Below is an example demonstrating how to build custom validations in Spring Boot. The example covers all three types of validations \u2014 single-field, multi-field (cross-field), and stateful validations using Spring properties. Each section introduces the concept followed by the respective code snippet. This complete example can be directly used as a working Spring Boot project.<\/p>\n<h3>2.1 Add Required Dependencies<\/h3>\n<p>To enable validation, include the <code>spring-boot-starter-validation<\/code> dependency along with <code>spring-boot-starter-web<\/code> in your <code>pom.xml<\/code>. The validation starter provides the Jakarta Bean Validation API used by Spring Boot.<\/p>\n<pre class=\"brush:xml; wrap-lines:false;\">\n&lt;dependencies&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-boot-starter-validation&lt;\/artifactId&gt;\n    &lt;\/dependency&gt;\n&lt;\/dependencies&gt;\n<\/pre>\n<h3>2.2 Define the Main Spring Boot Application Class<\/h3>\n<p>The main application class bootstraps the Spring Boot application. Annotating it with <code>@SpringBootApplication<\/code> enables component scanning and auto-configuration.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\npackage com.example.validationdemo;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class ValidationDemoApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(ValidationDemoApplication.class, args);\n    }\n}\n<\/pre>\n<h3>2.3 Create a Request DTO with Annotations<\/h3>\n<p>The DTO class represents the incoming request payload. It uses custom and standard validation annotations on its fields. Here, <code>@ValidUsername<\/code> ensures that the username starts with a prefix, <code>@ValidPassword<\/code> enforces password rules from configuration, and <code>@ValidDateRange<\/code> ensures that <code>startDate<\/code> is before <code>endDate<\/code>.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\npackage com.example.validationdemo.dto;\n\nimport com.example.validationdemo.validation.*;\nimport jakarta.validation.constraints.NotNull;\nimport java.time.LocalDate;\n\n@ValidDateRange\npublic class UserRequest {\n\n    @NotNull\n    @ValidUsername(prefix = \"emp_\")\n    private String username;\n\n    @ValidPassword\n    private String password;\n\n    private LocalDate startDate;\n    private LocalDate endDate;\n\n    \/\/ Getters and Setters\n    public String getUsername() { return username; }\n    public void setUsername(String username) { this.username = username; }\n\n    public String getPassword() { return password; }\n    public void setPassword(String password) { this.password = password; }\n\n    public LocalDate getStartDate() { return startDate; }\n    public void setStartDate(LocalDate startDate) { this.startDate = startDate; }\n\n    public LocalDate getEndDate() { return endDate; }\n    public void setEndDate(LocalDate endDate) { this.endDate = endDate; }\n}\n<\/pre>\n<h3>2.4 Build a REST Controller for Validation<\/h3>\n<p>The controller defines a REST endpoint to handle POST requests. The <code>@Valid<\/code> annotation ensures the request body is validated before the method executes. If validation fails, Spring automatically returns a 400 Bad Request response with validation messages.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\npackage com.example.validationdemo.controller;\n\nimport com.example.validationdemo.dto.UserRequest;\nimport jakarta.validation.Valid;\nimport org.springframework.web.bind.annotation.*;\n\n@RestController\n@RequestMapping(\"\/api\/users\")\npublic class UserController {\n\n    @PostMapping\n    public String createUser(@Valid @RequestBody UserRequest request) {\n        return \"User Created: \" + request.getUsername();\n    }\n}\n<\/pre>\n<h3>2.5 Define a Custom Annotation for Single-Field Validation<\/h3>\n<p>This custom annotation <code>@ValidUsername<\/code> checks whether a field value starts with a given prefix. It uses the <code>Constraint<\/code> annotation to link to its validator class.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ ValidUsername.java\npackage com.example.validationdemo.validation;\n\nimport jakarta.validation.Constraint;\nimport jakarta.validation.Payload;\nimport java.lang.annotation.*;\n\n@Documented\n@Constraint(validatedBy = UsernameValidator.class)\n@Target({ElementType.FIELD})\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ValidUsername {\n    String message() default \"Username must start with prefix\";\n    Class&lt;?&gt;[] groups() default {};\n    Class&lt;? extends Payload&gt;[] payload() default {};\n    String prefix() default \"user_\";\n}\n<\/pre>\n<h4>2.5.1 Implement the Single-Field Validator Logic<\/h4>\n<p>The <code>UsernameValidator<\/code> class implements <code>ConstraintValidator<\/code> and contains logic to validate whether the provided value starts with the defined prefix. The prefix is read from the annotation.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ UsernameValidator.java\npackage com.example.validationdemo.validation;\n\nimport jakarta.validation.ConstraintValidator;\nimport jakarta.validation.ConstraintValidatorContext;\n\npublic class UsernameValidator implements ConstraintValidator&lt;ValidUsername, String&gt; {\n\n    private String prefix;\n\n    @Override\n    public void initialize(ValidUsername constraintAnnotation) {\n        this.prefix = constraintAnnotation.prefix();\n    }\n\n    @Override\n    public boolean isValid(String value, ConstraintValidatorContext context) {\n        if (value == null) return false;\n        return value.startsWith(prefix);\n    }\n}\n<\/pre>\n<h3>2.6 Define a Custom Annotation for Multi-Field Validation<\/h3>\n<p>The <code>@ValidDateRange<\/code> annotation is applied at the class level. It ensures that one field depends on another\u2014in this case, verifying that <code>startDate<\/code> occurs before <code>endDate<\/code>.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ ValidDateRange.java\npackage com.example.validationdemo.validation;\n\nimport jakarta.validation.Constraint;\nimport jakarta.validation.Payload;\nimport java.lang.annotation.*;\n\n@Documented\n@Constraint(validatedBy = DateRangeValidator.class)\n@Target({ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ValidDateRange {\n    String message() default \"Start date must be before end date\";\n    Class&lt;?&gt;[] groups() default {};\n    Class&lt;? extends Payload&gt;[] payload() default {};\n}\n<\/pre>\n<h4>2.6.1 Implement the Multi-Field Validator Logic<\/h4>\n<p>The <code>DateRangeValidator<\/code> implements validation logic that checks whether the <code>startDate<\/code> precedes the <code>endDate<\/code>. If either date is null, the check is skipped to allow optional fields.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ DateRangeValidator.java\npackage com.example.validationdemo.validation;\n\nimport com.example.validationdemo.dto.UserRequest;\nimport jakarta.validation.ConstraintValidator;\nimport jakarta.validation.ConstraintValidatorContext;\n\npublic class DateRangeValidator implements ConstraintValidator&lt;ValidDateRange, UserRequest&gt; {\n\n    @Override\n    public boolean isValid(UserRequest request, ConstraintValidatorContext context) {\n        if (request.getStartDate() == null || request.getEndDate() == null)\n            return true;\n        return request.getStartDate().isBefore(request.getEndDate());\n    }\n}\n<\/pre>\n<h3>2.7 Create a Custom Password Validation Using Application Properties<\/h3>\n<p>The <code>@ValidPassword<\/code> annotation defines a field-level constraint. The actual validation rule will rely on a value from <code>application.properties<\/code>, making it stateful and configurable without code changes.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ ValidPassword.java\npackage com.example.validationdemo.validation;\n\nimport jakarta.validation.Constraint;\nimport jakarta.validation.Payload;\nimport java.lang.annotation.*;\n\n@Documented\n@Constraint(validatedBy = PasswordPolicyValidator.class)\n@Target({ElementType.FIELD})\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ValidPassword {\n    String message() default \"Password must meet policy requirements\";\n    Class&lt;?&gt;[] groups() default {};\n    Class&lt;? extends Payload&gt;[] payload() default {};\n}\n<\/pre>\n<h4>2.7.1 Implement the Stateful Password Validator<\/h4>\n<p>The <code>PasswordPolicyValidator<\/code> uses Spring\u2019s <code>@Value<\/code> annotation to inject a configuration property for minimum password length. This allows runtime flexibility and application-level policy enforcement.<\/p>\n<pre class=\"brush:java; wrap-lines:false;\">\n\/\/ PasswordPolicyValidator.java\npackage com.example.validationdemo.validation;\n\nimport jakarta.validation.ConstraintValidator;\nimport jakarta.validation.ConstraintValidatorContext;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class PasswordPolicyValidator implements ConstraintValidator&lt;ValidPassword, String&gt; {\n\n    @Value(\"${validation.password.min-length:8}\")\n    private int minLength;\n\n    @Override\n    public boolean isValid(String value, ConstraintValidatorContext context) {\n        if (value == null) return false;\n        return value.length() &gt;= minLength;\n    }\n}\n<\/pre>\n<h3>2.8 Add Configuration in application.properties<\/h3>\n<p>The configuration defines a property to control the minimum password length used by <code>ValidPassword<\/code> validation. This allows administrators to adjust password policies dynamically.<\/p>\n<pre class=\"brush:plain; wrap-lines:false;\">\nserver.port=8080\nvalidation.password.min-length=6\n<\/pre>\n<h3>2.9 Running the Application and Viewing Output<\/h3>\n<p>Once the Spring Boot application is up and running on port 8080, you can test your validation logic using curl commands from your terminal. Below are two examples showing how the validation behaves for both valid and invalid inputs.<\/p>\n<h4>2.9.1 Example: Valid Request<\/h4>\n<p>This example sends a valid JSON payload where all validation rules pass.  The username starts with <code>emp_<\/code>, the password meets the minimum length defined in <code>application.properties<\/code>, and the start date precedes the end date.  The API successfully creates the user and returns a 200 OK response.<\/p>\n<pre class=\"brush:plain; wrap-lines:false;\">\ncurl -X POST http:\/\/localhost:8080\/api\/users \\\n-H \"Content-Type: application\/json\" \\\n-d '{\n  \"username\": \"emp_john\",\n  \"password\": \"mypassword\",\n  \"startDate\": \"2025-01-01\",\n  \"endDate\": \"2025-01-10\"\n}'\n\nResponse: 200 OK\n\"User Created: emp_john\"\n<\/pre>\n<p>This example shows a successful API request where all validation rules pass. The username starts with the required prefix (emp_), the password meets the minimum length defined in the application properties, and the start date is before the end date. When you send this request, the Spring Boot controller processes it successfully and returns a 200 OK response along with the confirmation message.<\/p>\n<h4>2.9.2 Example: Invalid Request and Error Response<\/h4>\n<p>This example demonstrates a request that violates multiple validation rules. The username does not begin with the required prefix, the password is shorter than the configured minimum length, and the start date occurs after the end date.  Spring Boot automatically responds with a <code>400 Bad Request<\/code> and includes detailed validation error messages.<\/p>\n<pre class=\"brush:plain; wrap-lines:false;\">\ncurl -X POST http:\/\/localhost:8080\/api\/users \\\n-H \"Content-Type: application\/json\" \\\n-d '{\n  \"username\": \"john\",\n  \"password\": \"123\",\n  \"startDate\": \"2025-01-10\",\n  \"endDate\": \"2025-01-01\"\n}'\n\nResponse: 400 Bad Request\n{\n  \"errors\": [\n    \"Username must start with prefix\",\n    \"Password must meet policy requirements\",\n    \"Start date must be before end date\"\n  ]\n}\n<\/pre>\n<h2><a name=\"section-3\"><\/a>3. Conclusion<\/h2>\n<p>Spring Boot\u2019s Bean Validation framework provides an elegant, extensible way to enforce business rules. By creating custom annotations and validators, you can handle complex scenarios including multi-field checks and validations that depend on external state (such as configuration properties).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bean Validation is a core feature of Spring Boot used to enforce rules on Java objects before they are processed or persisted. While basic validations like @NotNull or @Email cover most cases, real-world applications often need custom and stateful validations \u2014 where validation logic depends on multiple fields, external configurations, or even runtime data. Let &hellip;<\/p>\n","protected":false},"author":26931,"featured_media":121875,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[854,292],"class_list":["post-138382","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring-boot","tag-validators"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-27T16:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Yatin Batra\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yatin Batra\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html\"},\"author\":{\"name\":\"Yatin Batra\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cda31a4c1965373fed40c8907dc09b8d\"},\"headline\":\"Developing Stateful Custom Bean Validation Using Spring Boot\",\"datePublished\":\"2025-10-27T16:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html\"},\"wordCount\":904,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"keywords\":[\"Spring Boot\",\"Validators\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html\",\"name\":\"Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"datePublished\":\"2025-10-27T16:00:00+00:00\",\"description\":\"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/spring-boot-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/developing-stateful-custom-bean-validation-using-spring-boot.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Developing Stateful Custom Bean Validation Using Spring Boot\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cda31a4c1965373fed40c8907dc09b8d\",\"name\":\"Yatin Batra\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/Yatin.batra_.jpg\",\"caption\":\"Yatin Batra\"},\"description\":\"An experience full-stack engineer well versed with Core Java, Spring\\\/Springboot, MVC, Security, AOP, Frontend (Angular &amp; React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).\",\"sameAs\":[\"https:\\\/\\\/www.javacodegeeks.com\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/yatin-batra\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks","description":"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html","og_locale":"en_US","og_type":"article","og_title":"Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks","og_description":"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.","og_url":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2025-10-27T16:00:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","type":"image\/jpeg"}],"author":"Yatin Batra","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Yatin Batra","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html"},"author":{"name":"Yatin Batra","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cda31a4c1965373fed40c8907dc09b8d"},"headline":"Developing Stateful Custom Bean Validation Using Spring Boot","datePublished":"2025-10-27T16:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html"},"wordCount":904,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","keywords":["Spring Boot","Validators"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html","url":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html","name":"Developing Stateful Custom Bean Validation Using Spring Boot - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","datePublished":"2025-10-27T16:00:00+00:00","description":"Spring custom stateful bean validation: Learn how to implement spring custom stateful bean validation for robust data integrity.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2024\/04\/spring-boot-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/developing-stateful-custom-bean-validation-using-spring-boot.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Developing Stateful Custom Bean Validation Using Spring Boot"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cda31a4c1965373fed40c8907dc09b8d","name":"Yatin Batra","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/12\/Yatin.batra_.jpg","caption":"Yatin Batra"},"description":"An experience full-stack engineer well versed with Core Java, Spring\/Springboot, MVC, Security, AOP, Frontend (Angular &amp; React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).","sameAs":["https:\/\/www.javacodegeeks.com"],"url":"https:\/\/www.javacodegeeks.com\/author\/yatin-batra"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/138382","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/26931"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=138382"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/138382\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/121875"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=138382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=138382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=138382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}