Jackson এবং Bean Validation Integration

জ্যাকসন (Jackson) - Java Technologies

355

Jackson এবং Bean Validation (JSR 380) একসাথে ব্যবহার করা হলে, আমরা JSON ডেটা প্রসেস করার সময় ভ্যালিডেশন নিয়ম প্রয়োগ করতে পারি। এটি বিশেষভাবে RESTful API-তে ইনপুট ডেটার বৈধতা যাচাইয়ের জন্য কার্যকর।


প্রয়োজনীয় প্রযুক্তি

  1. Jackson: JSON ডেটা সিরিয়ালাইজ/ডেসিরিয়ালাইজ করার জন্য।
  2. Bean Validation: Java Bean ডেটা ভ্যালিডেশনের জন্য।
  3. Hibernate Validator: Bean Validation-এর জন্য একটি জনপ্রিয় ইমপ্লিমেন্টেশন।

সেটআপ

Maven ডিপেন্ডেন্সি

<dependencies>
    <!-- Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>

    <!-- Hibernate Validator -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>8.0.0.Final</version>
    </dependency>

    <!-- Bean Validation API -->
    <dependency>
        <groupId>jakarta.validation</groupId>
        <artifactId>jakarta.validation-api</artifactId>
        <version>3.0.2</version>
    </dependency>

    <!-- Optional: Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.9</version>
    </dependency>
</dependencies>

Bean Validation সহ মডেল ক্লাস তৈরি

উদাহরণ:

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class User {
    @NotNull(message = "ID cannot be null")
    private Integer id;

    @NotBlank(message = "Name cannot be blank")
    @Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
    private String name;

    @Email(message = "Email should be valid")
    private String email;

    // Getters and Setters
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Jackson এবং Bean Validation একত্রে ব্যবহার

উদাহরণ:

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;

import java.util.Set;

public class JacksonBeanValidationExample {
    public static void main(String[] args) throws Exception {
        // Jackson ObjectMapper
        ObjectMapper objectMapper = new ObjectMapper();

        // JSON ইনপুট
        String json = "{ \"id\": null, \"name\": \"Jo\", \"email\": \"invalid-email\" }";

        // JSON থেকে User অবজেক্ট ডেসিরিয়ালাইজ করা
        User user = objectMapper.readValue(json, User.class);

        // Bean Validation
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        Set<ConstraintViolation<User>> violations = validator.validate(user);

        // Validation ফলাফল প্রিন্ট করা
        if (!violations.isEmpty()) {
            for (ConstraintViolation<User> violation : violations) {
                System.out.println(violation.getPropertyPath() + ": " + violation.getMessage());
            }
        } else {
            System.out.println("User object is valid.");
        }
    }
}

JSON ইনপুট:

{
  "id": null,
  "name": "Jo",
  "email": "invalid-email"
}

আউটপুট:

id: ID cannot be null
name: Name must be between 3 and 50 characters
email: Email should be valid

Spring Boot-এ Jackson এবং Bean Validation Integration

Spring Boot-এ আমরা Jackson এবং Bean Validation-এর ইন্টিগ্রেশন খুব সহজেই করতে পারি। Spring Boot স্বয়ংক্রিয়ভাবে @Valid এবং @Validated অ্যানোটেশন সহ Bean Validation সক্ষম করে।

REST Controller উদাহরণ:

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;

@RestController
@RequestMapping("/users")
@Validated
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
        // যদি User অবজেক্ট বৈধ হয়
        return ResponseEntity.ok("User created successfully!");
    }
}

অবৈধ ইনপুটের জন্য আউটপুট (Spring Boot Default Response):

{
  "timestamp": "2024-12-21T14:22:35.123+00:00",
  "status": 400,
  "errors": [
    {
      "field": "id",
      "message": "ID cannot be null"
    },
    {
      "field": "name",
      "message": "Name must be between 3 and 50 characters"
    },
    {
      "field": "email",
      "message": "Email should be valid"
    }
  ]
}

কাস্টম Exception Handling

Custom Exception Handler:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error -> {
            errors.put(error.getField(), error.getDefaultMessage());
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}

কাস্টম আউটপুট:

{
  "id": "ID cannot be null",
  "name": "Name must be between 3 and 50 characters",
  "email": "Email should be valid"
}

  1. Jackson এবং Bean Validation Integration JSON ডেটা সিরিয়ালাইজ/ডেসিরিয়ালাইজ এবং ভ্যালিডেশনের জন্য অত্যন্ত কার্যকর।
  2. Bean Validation-এর সাহায্যে ইনপুট ডেটা বৈধতা যাচাই করা যায়।
  3. Spring Boot ব্যবহার করলে @Valid এবং @Validated দিয়ে সহজেই এই ফিচার ইমপ্লিমেন্ট করা যায়।
  4. কাস্টম Exception Handler ব্যবহার করে নির্দিষ্ট ফরম্যাটে ভ্যালিডেশন এরর মেসেজ প্রদর্শন করা সম্ভব।

এই Integration REST API-তে ইনপুট ভ্যালিডেশনের জন্য সবচেয়ে সাধারণ এবং শক্তিশালী পদ্ধতিগুলোর একটি।

Content added By

Bean Validation একটি Java Specification যা Java ক্লাস, প্রপার্টি এবং মেথডের উপর কনস্ট্রেইন্ট (constraint) আরোপ করতে ব্যবহৃত হয়। এটি সাধারণত Jakarta Bean Validation (JSR 380) অথবা Hibernate Validator এর মাধ্যমে ইমপ্লিমেন্ট করা হয়। Jackson এর সাথে Bean Validation ইন্টিগ্রেশন ব্যবহার করে ডেটা ভ্যালিডেশন এবং JSON সিরিয়ালাইজেশন/ডেসিরিয়ালাইজেশন আরো কার্যকর করা যায়।


Bean Validation এর ভূমিকা

  1. ডেটা ভ্যালিডেশন: ইনপুট ডেটা (JSON, XML) ডেসিরিয়ালাইজ করার সময় ডেটা সঠিক কিনা তা নিশ্চিত করা।
  2. কোড সিম্পলিসিটি: ভ্যালিডেশন লজিক প্রপার্টি বা মডেল স্তরে সরাসরি ডিক্লেয়ার করা যায়।
  3. API সিকিউরিটি: REST API এর ডেটা ইন্টিগ্রিটির জন্য উপযোগী।
  4. অটোমেটিক চেকিং: ভ্যালিডেশন কনস্ট্রেইন্ট স্বয়ংক্রিয়ভাবে চেক হয়।

Bean Validation এর অ্যানোটেশন

Bean Validation-এ নিম্নলিখিত অ্যানোটেশনগুলো সাধারণত ব্যবহৃত হয়:

  • @NotNull: ভ্যালু null হতে পারবে না।
  • @Size: একটি স্ট্রিং, কালেকশন বা অ্যারের সাইজ নির্ধারণ করে।
  • @Min এবং @Max: সংখ্যা সংক্রান্ত সীমা নির্ধারণ করে।
  • @Pattern: একটি স্ট্রিং নির্দিষ্ট রেগুলার এক্সপ্রেশন অনুযায়ী ভ্যালিড হয় কিনা চেক করে।
  • @Email: একটি স্ট্রিং ইমেইল অ্যাড্রেস হিসেবে ভ্যালিড কিনা তা নিশ্চিত করে।

Jackson এবং Bean Validation এর Integration

Jackson-এর মাধ্যমে JSON ডেটা ডেসিরিয়ালাইজ করার সময় Bean Validation ব্যবহার করে ডেটা ভ্যালিডেশন করা যায়। এটি সাধারণত Spring Boot বা Hibernate Validator এর মাধ্যমে ইন্টিগ্রেটেড করা হয়।


উদাহরণ: Bean Validation এর ব্যবহার এবং Jackson Integration

১. Maven ডিপেন্ডেন্সি

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId>
    <version>5.0.0</version>
</dependency>

২. Model Class তৈরি করুন

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class User {

    @NotNull(message = "Name cannot be null")
    @Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
    private String name;

    @Email(message = "Email should be valid")
    private String email;

    @Min(value = 18, message = "Age must be at least 18")
    private int age;

    // Getters এবং Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

৩. JSON Deserialization এর সময় Bean Validation প্রয়োগ করুন

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;

import java.util.Set;

public class BeanValidationExample {
    public static void main(String[] args) {
        String json = """
        {
            "name": "Jo",
            "email": "invalid-email",
            "age": 15
        }
        """;

        try {
            ObjectMapper objectMapper = new ObjectMapper();

            // JSON থেকে User অবজেক্টে রূপান্তর
            User user = objectMapper.readValue(json, User.class);

            // Bean Validation চেক করা
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();

            Set<ConstraintViolation<User>> violations = validator.validate(user);

            if (!violations.isEmpty()) {
                for (ConstraintViolation<User> violation : violations) {
                    System.out.println(violation.getMessage());
                }
            } else {
                System.out.println("User is valid: " + user.getName());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

আউটপুট:

Name must be between 3 and 50 characters
Email should be valid
Age must be at least 18

Spring Boot এর মাধ্যমে সহজ Integration

Controller এর উদাহরণ

Spring Boot ব্যবহার করলে ভ্যালিডেশন আরো সহজ হয়। Spring @Valid অ্যানোটেশন সরাসরি ব্যবহার করে Bean Validation ইন্টিগ্রেট করা যায়।

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import jakarta.validation.Valid;

@RestController
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
        return ResponseEntity.ok("User is valid: " + user.getName());
    }
}

উপকারিতা

  1. ডেটা ইন্টিগ্রিটি: Bean Validation নিশ্চিত করে যে ইনপুট ডেটা সর্বদা নির্ধারিত কনস্ট্রেইন্ট মেনে চলবে।
  2. ডাইনামিক Integration: Jackson এর মাধ্যমে JSON ডেসিরিয়ালাইজ করার সময় অটোমেটিক ভ্যালিডেশন।
  3. অ্যাপ্লিকেশন সিকিউরিটি: API ভ্যালিডেশন নিশ্চিত করে যে অননুমোদিত বা ভুল ডেটা প্রসেস করা হবে না।
  4. কমপ্লেক্সিটি হ্রাস: কোডের অন্যত্র ভ্যালিডেশন লজিক না লিখে সরাসরি মডেলে সংজ্ঞায়িত করা যায়।

Jackson এবং Bean Validation এর ইন্টিগ্রেশন ডেটা প্রক্রিয়াকরণের সময় ভ্যালিডেশন নিশ্চিত করার একটি শক্তিশালী এবং কার্যকর পদ্ধতি। এটি বিশেষ করে RESTful API ডেভেলপমেন্টে সঠিক এবং নিরাপদ ডেটা হ্যান্ডলিংয়ের জন্য অত্যন্ত কার্যকর।

Content added By

Java Bean Validation অ্যানোটেশন যেমন @NotNull, @Size, এবং অন্যান্য হ্যান্ডল করতে Jackson এবং Bean Validation API (যেমন Hibernate Validator) একত্রে কাজ করে। এগুলো সাধারণত ডেটা ভ্যালিডেশন নিশ্চিত করার জন্য ব্যবহৃত হয়।


Java Bean Validation এর প্রধান উদ্দেশ্য

  • @NotNull: কোনো ফিল্ড null হতে পারবে না।
  • @Size: কোনো ফিল্ডের দৈর্ঘ্য বা সাইজ নির্দিষ্ট সীমার মধ্যে থাকতে হবে।
  • @Min, @Max: একটি ফিল্ডের সর্বনিম্ন এবং সর্বোচ্চ মান নির্ধারণ।
  • @Pattern: একটি ফিল্ড নির্দিষ্ট প্যাটার্ন অনুসরণ করছে কি না তা যাচাই।

Jackson এর মাধ্যমে Validation Integration

প্রয়োজনীয় ডিপেনডেন্সি

Maven Dependency:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.4.Final</version>
</dependency>

Step-by-Step উদাহরণ

১. মডেল ক্লাসে Validation Annotation যোগ করা

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {
    @NotNull(message = "Name cannot be null")
    private String name;

    @Size(min = 1, max = 50, message = "Name length must be between 1 and 50 characters")
    private String username;

    @NotNull(message = "Email cannot be null")
    private String email;

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

২. Validation চেক করার জন্য Validator ব্যবহার করা

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.ConstraintViolation;
import java.util.Set;

public class ValidationExample {
    public static void main(String[] args) {
        // Validator তৈরি
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        // মডেল অবজেক্ট তৈরি
        User user = new User();
        user.setName(null); // Invalid
        user.setUsername(""); // Invalid
        user.setEmail(null); // Invalid

        // Validation চেক
        Set<ConstraintViolation<User>> violations = validator.validate(user);

        // Validation ত্রুটি প্রদর্শন
        for (ConstraintViolation<User> violation : violations) {
            System.out.println(violation.getPropertyPath() + ": " + violation.getMessage());
        }
    }
}

Output:

name: Name cannot be null
username: Name length must be between 1 and 50 characters
email: Email cannot be null

৩. Spring Boot এর সাথে Validation ব্যবহার করা

Spring Boot এর ক্ষেত্রে Validation সহজে REST API তে ব্যবহার করা যায়।

Spring Boot মডেল ক্লাস:

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {
    @NotNull(message = "Name cannot be null")
    private String name;

    @Size(min = 1, max = 50, message = "Username length must be between 1 and 50 characters")
    private String username;

    @NotNull(message = "Email cannot be null")
    private String email;

    // Getters and Setters
}

Spring REST Controller:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
        return new ResponseEntity<>("User is valid!", HttpStatus.OK);
    }
}

API Call উদাহরণ:

Request:

{
  "name": null,
  "username": "",
  "email": null
}

Response:

{
  "timestamp": "2024-12-21T10:30:00.000+00:00",
  "status": 400,
  "errors": [
    "Name cannot be null",
    "Username length must be between 1 and 50 characters",
    "Email cannot be null"
  ]
}

৪. Validation Error হ্যান্ডল করা

Spring Boot এ কাস্টম Error Response তৈরি করতে একটি ExceptionHandler ব্যবহার করা হয়।

Custom Exception Handler:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            errors.put(error.getField(), error.getDefaultMessage());
        }
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
}

Response:

{
  "name": "Name cannot be null",
  "username": "Username length must be between 1 and 50 characters",
  "email": "Email cannot be null"
}

  • @NotNull এবং @Size এর মতো Validation অ্যানোটেশন ব্যবহার করে ডেটার মান যাচাই করা সহজ হয়।
  • Jackson এবং Bean Validation এর ইন্টিগ্রেশন JSON ডেটা ভ্যালিডেশন নিশ্চিত করে।
  • Spring Boot এ @Valid এবং Exception Handler ব্যবহার করে REST API তে Validation সহজে প্রয়োগ করা যায়।
Content added By

Jackson ব্যবহার করে JSON ডেটা প্রসেস করার সময় Validation Error Handling এবং Custom Exception Management অত্যন্ত গুরুত্বপূর্ণ। ডেটা অনুপযুক্ত বা অসম্পূর্ণ হলে সঠিক Validation এবং Exception Handling একটি API বা অ্যাপ্লিকেশনের নির্ভরযোগ্যতা এবং নিরাপত্তা নিশ্চিত করে।


Validation Error Handling

Jackson সাধারণত Java Bean Validation বা কাস্টম লজিক দিয়ে JSON ডেটার ভ্যালিডেশন পরিচালনা করতে পারে। Java Bean Validation API (যেমন javax.validation বা jakarta.validation) এর মাধ্যমে ফিল্ডগুলোর উপর বিধিনিষেধ আরোপ করা যায়।

1. Bean Validation Integration

ডিপেন্ডেন্সি:
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.5.Final</version>
</dependency>
মডেল ক্লাস:
import javax.validation.constraints.*;

class User {
    @NotNull(message = "ID cannot be null")
    public Integer id;

    @NotBlank(message = "Name cannot be blank")
    public String name;

    @Email(message = "Email must be valid")
    public String email;

    @Min(value = 18, message = "Age must be at least 18")
    public int age;
}
Validation এবং Exception Handling:
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.validation.*;
import java.util.Set;

public class Main {
    public static void main(String[] args) throws Exception {
        String json = """
        {
            "id": null,
            "name": " ",
            "email": "invalid_email",
            "age": 16
        }
        """;

        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(json, User.class);

        // Validate the User object
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        Set<ConstraintViolation<User>> violations = validator.validate(user);

        if (!violations.isEmpty()) {
            for (ConstraintViolation<User> violation : violations) {
                System.out.println("Validation Error: " + violation.getMessage());
            }
        } else {
            System.out.println("User is valid!");
        }
    }
}
আউটপুট:
Validation Error: ID cannot be null
Validation Error: Name cannot be blank
Validation Error: Email must be valid
Validation Error: Age must be at least 18

Custom Exception Management

Jackson JSON serialization/deserialization প্রক্রিয়ার সময় যেকোনো ত্রুটি কাস্টমাইজ করতে সক্ষম। আপনি কাস্টম Exception Handler ব্যবহার করে ত্রুটির ধরন অনুযায়ী কাস্টম মেসেজ বা লজিক সংযুক্ত করতে পারেন।

2. Custom Exception Handler

Custom Exception Class:
public class CustomException extends RuntimeException {
    public CustomException(String message) {
        super(message);
    }
}
Exception Handling Example:
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) {
        String invalidJson = """
        {
            "id": "invalid",
            "name": "John Doe"
        }
        """;

        try {
            ObjectMapper objectMapper = new ObjectMapper();
            User user = objectMapper.readValue(invalidJson, User.class);
        } catch (JsonParseException e) {
            throw new CustomException("JSON Parsing Error: " + e.getMessage());
        } catch (JsonMappingException e) {
            throw new CustomException("JSON Mapping Error: " + e.getMessage());
        } catch (Exception e) {
            throw new CustomException("Unknown Error: " + e.getMessage());
        }
    }
}
আউটপুট:
Exception in thread "main" CustomException: JSON Mapping Error: Cannot deserialize value of type `java.lang.Integer` from String "invalid": not a valid Integer value

Global Exception Handling in Spring Boot

Spring Boot-এ @RestControllerAdvice ব্যবহার করে Global Exception Handling করা যায়।

Global Exception Handler:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<String> handleCustomException(CustomException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGeneralException(Exception ex) {
        return new ResponseEntity<>("An unexpected error occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

3. Combining Validation and Custom Exception

Spring Boot-এ Bean Validation এবং Exception Handling একত্রে ব্যবহার করা যায়।

Controller Example:
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
        return ResponseEntity.ok("User created successfully");
    }
}
Global Exception Example:
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.stream.Collectors;

@ControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
        String errors = ex.getBindingResult()
                          .getFieldErrors()
                          .stream()
                          .map(error -> error.getField() + ": " + error.getDefaultMessage())
                          .collect(Collectors.joining(", "));
        return ResponseEntity.badRequest().body("Validation Errors: " + errors);
    }
}
আউটপুট (Validation Error):
Validation Errors: id: ID cannot be null, name: Name cannot be blank, email: Email must be valid, age: Age must be at least 18

Key Takeaways:

  1. Validation:
    • Bean Validation API দিয়ে JSON ডেটার সঠিকতা যাচাই করা যায়।
    • Spring Boot-এ সরাসরি @Valid ব্যবহার করে সহজে Validation ইন্টিগ্রেট করা যায়।
  2. Custom Exception:
    • Jackson JSON ত্রুটিগুলো কাস্টমাইজ করা যায়।
    • Global Exception Handling দিয়ে অ্যাপ্লিকেশনকে আরও দৃঢ় করা যায়।
  3. Spring Boot Integration:
    • Validation এবং Exception Handling Spring Boot-এ আরও কার্যকরভাবে ব্যবহৃত হয়।
    • API তে মানসম্পন্ন ত্রুটি মেসেজ প্রদর্শন করা সহজ।

এই পদ্ধতিগুলো API ডেভেলপমেন্টে ত্রুটিমুক্ত এবং নিরাপদ ডেটা হ্যান্ডলিং নিশ্চিত করে।

Content added By

Jackson একটি জনপ্রিয় Java লাইব্রেরি যা JSON ডেটা serialization এবং deserialization-এর জন্য ব্যবহৃত হয়। Complex validation scenarios হ্যান্ডল করার জন্য Jackson বিভিন্ন টুল এবং কাস্টম কৌশল প্রদান করে। এটি মূলত API-তে প্রাপ্ত JSON ডেটার বৈধতা যাচাই এবং সঠিকভাবে প্রক্রিয়াকরণের জন্য গুরুত্বপূর্ণ।


Complex Validation কেন গুরুত্বপূর্ণ?

  1. Dynamic Data Validation: JSON ডেটার কাঠামো এবং মান নির্ভুল কিনা তা নিশ্চিত করা।
  2. Custom Rules Implementation: কাস্টম validation rules প্রয়োগ করা।
  3. Error Reporting: ভুল JSON ডেটার জন্য যথাযথ ত্রুটি বার্তা প্রদান।
  4. Nested Structure Validation: জটিল এবং nested JSON স্ট্রাকচারের ডেটা যাচাই।

Validation-এর জন্য টুলস এবং পদ্ধতি

1. Annotations দিয়ে Validation

Java Bean Validation API (JSR-380) এর annotations ব্যবহার করে Jackson-এর মাধ্যমে সহজেই validation করা যায়।

Dependency (Hibernate Validator):

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>

উদাহরণ:

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class User {
    @NotNull(message = "Name cannot be null")
    @Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
    private String name;

    @NotNull(message = "Email cannot be null")
    private String email;

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

Validation Integration:

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;

public class AnnotationValidationExample {
    public static void main(String[] args) {
        try {
            String json = """
                          {
                              "name": "John",
                              "email": null
                          }
                          """;

            ObjectMapper mapper = new ObjectMapper();
            User user = mapper.readValue(json, User.class);

            // Validator তৈরি
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();

            // Validate
            var violations = validator.validate(user);
            if (!violations.isEmpty()) {
                violations.forEach(violation -> System.out.println(violation.getMessage()));
            } else {
                System.out.println("Valid User: " + user.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

আউটপুট:

Email cannot be null

2. Custom Deserialization-এর মাধ্যমে Validation

Custom deserialization ব্যবহার করে JSON ডেটা validate এবং প্রক্রিয়াকরণ করা যায়।

উদাহরণ:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.io.IOException;

class User {
    private String name;

    @JsonDeserialize(using = CustomEmailDeserializer.class)
    private String email;

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

class CustomEmailDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String email = p.getText();
        if (email == null || !email.contains("@")) {
            throw new IOException("Invalid email format: " + email);
        }
        return email;
    }
}

ব্যবহার:

public class CustomDeserializerValidationExample {
    public static void main(String[] args) {
        try {
            String json = """
                          {
                              "name": "John",
                              "email": "invalidEmail"
                          }
                          """;

            ObjectMapper mapper = new ObjectMapper();
            User user = mapper.readValue(json, User.class);

            System.out.println("User: " + user.getName() + ", Email: " + user.getEmail());
        } catch (Exception e) {
            System.err.println("Validation Error: " + e.getMessage());
        }
    }
}

আউটপুট:

Validation Error: Invalid email format: invalidEmail

3. Custom Validator ব্যবহার

Custom Validator তৈরি করে জটিল validation নিয়ম প্রয়োগ করা যায়।

উদাহরণ:

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// Custom Annotation
@Constraint(validatedBy = PhoneNumberValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface ValidPhoneNumber {
    String message() default "Invalid phone number";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

// Validator Implementation
class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {
    @Override
    public boolean isValid(String phoneNumber, ConstraintValidatorContext context) {
        return phoneNumber != null && phoneNumber.matches("\\d{10}");
    }
}

Model Class:

public class Contact {
    @ValidPhoneNumber
    private String phoneNumber;

    // Getters and Setters
    public String getPhoneNumber() { return phoneNumber; }
    public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; }
}

ব্যবহার:

public class CustomValidatorExample {
    public static void main(String[] args) {
        Contact contact = new Contact();
        contact.setPhoneNumber("12345");

        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        var violations = validator.validate(contact);
        if (!violations.isEmpty()) {
            violations.forEach(violation -> System.out.println(violation.getMessage()));
        } else {
            System.out.println("Valid Phone Number: " + contact.getPhoneNumber());
        }
    }
}

আউটপুট:

Invalid phone number

4. Nested Object Validation

Nested objects বা জটিল JSON স্ট্রাকচারের validation সহজে করা যায়।

উদাহরণ:

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;

public class Order {
    @NotNull
    private String orderId;

    @Valid
    @NotNull
    private User user;

    // Getters and Setters
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }

    public User getUser() { return user; }
    public void setUser(User user) { this.user = user; }
}

Validation Integration:

public class NestedValidationExample {
    public static void main(String[] args) {
        try {
            String json = """
                          {
                              "orderId": "123",
                              "user": {
                                  "name": "John",
                                  "email": null
                              }
                          }
                          """;

            ObjectMapper mapper = new ObjectMapper();
            Order order = mapper.readValue(json, Order.class);

            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();

            var violations = validator.validate(order);
            if (!violations.isEmpty()) {
                violations.forEach(violation -> System.out.println(violation.getMessage()));
            } else {
                System.out.println("Valid Order ID: " + order.getOrderId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

আউটপুট:

Email cannot be null

  1. Basic Validation: Annotations ব্যবহার করে সহজেই validation পরিচালনা করা যায়।
  2. Complex Validation: কাস্টম deserializers এবং validators তৈরি করে আরও জটিল validation নিয়ম প্রয়োগ করা সম্ভব।
  3. Nested Validation: @Valid annotations ব্যবহার করে nested objects validate করা যায়।
  4. Error Handling: Jackson validation errors সহজেই রিপোর্ট করা যায়।

এই পদ্ধতিগুলো ব্যবহার করে জটিল validation scenarios Jackson-এর মাধ্যমে দক্ষতার সাথে হ্যান্ডল করা সম্ভব।

Content added By
Promotion

Are you sure to start over?

Loading...