> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/developer-guide-en/pjt-prepare/framework-guide/data-validation.md).

# Data Validation

This document explains how to perform data validation in the X2BEE Framework.

Validation can be implemented using Bean Validation and Custom Validators, and can be applied to VO objects used for data communication or to specific fields.

***

## Validation Methods

### Bean Validation

Specify an alias with the Alias annotation. Since data communication uses VOs, annotations provided by the jakarta.validation.constraints package are applied to VO objects.

{% code title="Group.java" %}

```java
package com.x2bee.api.bo.app.entity;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.apache.ibatis.type.Alias;
import com.x2bee.common.base.entity.AbstractEntity;
import lombok.Getter;
import lombok.Setter;

@Alias("group")
@Getter
@Setter
public class Group extends AbstractEntity {
    @NotNull
    String groupNo;

    @NotEmpty
    String groupName;
}
```

{% endcode %}

### Validation of @RequestBody Using @Valid

{% code title="SampleController.java (excerpt)" %}

```java
public class SampleController {
    ...

    @PostMapping("")
    public Response<String> registerSample(@RequestBody @Valid Sample sample) throws InterruptedException {
        ...
    }

    ...
}
```

{% endcode %}

### Validation of @PathVariable and @RequestParam Using @Validated

{% code title="SampleController.java (excerpt)" %}

```java
@RestController
@Validated
public class SampleController {
    @GetMapping("/users/{email}")
    public String getUserInfoByEmail(@PathVariable("email") @Email String email) {
        ....
    }
}
```

{% endcode %}

## Custom Validator

If you want to implement a validator that is not provided by the jakarta.validation.constraints package, proceed as follows.

### Creating a Custom Annotation

{% code title="LocaleConstraint.java" %}

```java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = LocaleValidator.class)
@Documented
public @interface LocaleConstraint {
    String message() default "Invalid Locale";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
```

{% endcode %}

### Creating a Custom Validator to Process the Custom Annotation

{% code title="LocaleValidator.java" %}

```java
public class LocaleValidator implements ConstraintValidator<LocaleConstraint, String> {
    public static final List<String> locales = Arrays.asList("ko_KR", "en_US");

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && locales.contains(value.toLowerCase());
    }
}
```

{% endcode %}

### Applying the Custom @LocaleConstraint Annotation for Validation

{% code title="Category.java" %}

```java
package com.plateer.x2co.api.prototype.entity;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

@Data
public class Category {
    @NotEmpty
    private String catTpCd;

    @NotBlank
    private String siteNo;

    @NotEmpty
    private String dpmlNo;

    @NotEmpty
    @LocaleConstraint // Applied as an annotation like this
    private String dbLocaleLanguage;

    @NotEmpty
    private int maxLvl = 0;

    @NotEmpty
    private int minLvl = 0;
}
```

{% endcode %}
