The Cinefinder API uses Jakarta Validation (formerly known as Bean Validation) to ensure data integrity and consistency. The API includes the Jakarta Validation API dependency for validation support.
The API includes the validation API but does not include a validation implementation like Hibernate Validator. For full validation support, consider adding:
import jakarta.validation.constraints.*;public record PeliculasDto( Integer id, @NotBlank(message = "El título es obligatorio") @Size(min = 1, max = 255, message = "El título debe tener entre 1 y 255 caracteres") String titulo, @NotBlank(message = "La sipnosis es obligatoria") @Size(max = 1000, message = "La sipnosis no puede exceder 1000 caracteres") String sipnosis, @NotNull(message = "La duración es obligatoria") @Positive(message = "La duración debe ser positiva") @Max(value = 600, message = "La duración no puede exceder 600 minutos") Integer duracion, @NotNull(message = "La categoría es obligatoria") @Positive(message = "El ID de categoría debe ser positivo") Integer categoria_id) {}
import jakarta.validation.constraints.*;public record CategoriasDto( Integer id, @NotBlank(message = "El nombre es obligatorio") @Size(min = 2, max = 100, message = "El nombre debe tener entre 2 y 100 caracteres") String nombre) {}
import jakarta.validation.constraints.*;public record ArtistasDto( @NotNull(message = "El DNI es obligatorio") @Positive(message = "El DNI debe ser positivo") Long dni, @NotBlank(message = "El nombre es obligatorio") @Size(min = 2, max = 100, message = "El nombre debe tener entre 2 y 100 caracteres") String nombre, @NotBlank(message = "El apellido es obligatorio") @Size(min = 2, max = 100, message = "El apellido debe tener entre 2 y 100 caracteres") String apellido, @NotBlank(message = "El tipo es obligatorio") @Pattern(regexp = "^(Actor|Director|Productor)$", message = "El tipo debe ser: Actor, Director o Productor") String tipo, @Size(max = 500, message = "La descripción no puede exceder 500 caracteres") String descripcion) {}
{ "type": "error", "code": "400", "details": "Errores de validación: {titulo=El título es obligatorio, sipnosis=La sipnosis es obligatoria, duracion=La duración debe ser positiva, categoria_id=La categoría es obligatoria}", "location": "uri=/peliculas", "moreInfo": "Verifique los datos enviados", "timestamp": "2026-03-04T10:30:45.123"}
You can create custom validation annotations for complex business rules:
import jakarta.validation.Constraint;import jakarta.validation.Payload;@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = TituloUnicoValidator.class)public @interface TituloUnico { String message() default "El título ya existe"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}
import jakarta.validation.ConstraintValidator;import jakarta.validation.ConstraintValidatorContext;public class TituloUnicoValidator implements ConstraintValidator<TituloUnico, String> { @Autowired private PeliculasRepository repository; @Override public boolean isValid(String titulo, ConstraintValidatorContext context) { if (titulo == null) return true; return !repository.existsByTitulo(titulo); }}
Use it in your DTO:
public record PeliculasDto( Integer id, @NotBlank @TituloUnico(message = "Ya existe una película con este título") String titulo, // ... other fields) {}
Use validation groups to apply different validation rules for different scenarios:
public interface CreateValidation {}public interface UpdateValidation {}public record PeliculasDto( @Null(groups = CreateValidation.class, message = "El ID debe ser nulo al crear") @NotNull(groups = UpdateValidation.class, message = "El ID es obligatorio al actualizar") Integer id, @NotBlank(groups = {CreateValidation.class, UpdateValidation.class}) String titulo) {}