0

I have already looked in stackoverflow and other websites but found nothing which worked for me.

(Spring boot 3)

Log : Resolved [jakarta.validation.ValidationException: HV000028: Unexpected exception during isValid call.]

-> Certainly due to my response from Postman

{
    "cause": {
        "cause": null,
        "message": "Cannot invoke \"com.laramendez.appweb.repository.ProgrammeRepository.existsByNom(String)\" because \"this.programmeRepository\" is null"
    },
    "message": "HV000028: Unexpected exception during isValid call."
}

dependencies in pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://stackoverflow.com/a/71416675/19092469 -->
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-hibernate5</artifactId>
        </dependency>

        <!-- Réduire code répétitif et source d'erreur (reduce boilerplate) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Réduire code répétitif et source d'erreur (reduce boilerplate) -->



        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

nomUniqueValidator

package com.laramendez.appweb.validation.validator;

import com.laramendez.appweb.repository.ProgrammeRepository;
import com.laramendez.appweb.validation.annotation.ProgrammeNomUnique;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;


@NoArgsConstructor
public class NomUniqueValidator implements ConstraintValidator<ProgrammeNomUnique, String> {

    private ProgrammeRepository programmeRepository;


    @Autowired
    public NomUniqueValidator(ProgrammeRepository programmeRepository) {
        this.programmeRepository = programmeRepository;
    }


    @Override
    public void initialize(ProgrammeNomUnique constraintAnnotation) {
    }

    @Override
    public boolean isValid(String nouveauNom, ConstraintValidatorContext constraintValidatorContext) {
        
        return !programmeRepository.existsByNom(nouveauNom);

    }
}

ProgrammeNomUnique

package com.laramendez.appweb.validation.annotation;

import com.laramendez.appweb.validation.validator.NomUniqueValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

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

@Constraint(validatedBy = NomUniqueValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ProgrammeNomUnique {

        // define default error message
        String message() default "Un programme porte déjà le même nom";

        // define default groups
        public Class<?>[] groups() default {};

        // define default payloads
        public Class<? extends Payload>[] payload() default {};

}

ProgrammeRepository

package com.laramendez.appweb.repository;

import com.laramendez.appweb.entity.Programme;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;


@CrossOrigin(origins = "http://localhost:4200")
@RepositoryRestResource(path = "programmes")
public interface ProgrammeRepository extends JpaRepository<Programme, Integer> {

    boolean existsByNom(String nom);
}

I'm using Spring Data Rest, that's why i do not have controller, dao and service.

I do not have nothing interesting in my properties.

enter image description here

Thanks !

My injection in my custom validator return null. Do someone know why? How to dix it?

UPDATE: I just kept an empty constructor like this with advice from M. Deinum but it still does not work, i have the same error

public class NomUniqueValidator implements ConstraintValidator<ProgrammeNomUnique, String> {

    @Autowired
    private ProgrammeRepository programmeRepository;

    public NomUniqueValidator() {
    }

    @Override
    public void initialize(ProgrammeNomUnique constraintAnnotation) {
    }

    @Override
    public boolean isValid(String nouveauNom, ConstraintValidatorContext constraintValidatorContext) {

        return !programmeRepository.existsByNom(nouveauNom);

    }
}

UPDATE: with advice from daniu I tried but I still have the same issue

@Component
public class NomUniqueValidator implements ConstraintValidator<ProgrammeNomUnique, String> {
//[...]
}

@Service
public class NomUniqueValidator implements ConstraintValidator<ProgrammeNomUnique, String> {
//[...]
}

UPDATE : with M. Deinum Advice, does not work

@Component
@Scope("request")
@RequiredArgsConstructor
public class NomUniqueValidator implements ConstraintValidator<ProgrammeNomUnique, String> {

        @Autowired
        private  ProgrammeRepository programmeRepository;


    @Override
    public void initialize(ProgrammeNomUnique constraintAnnotation) {
    }

    @Override
    public boolean isValid(String nouveauNom, ConstraintValidatorContext constraintValidatorContext) {
        return !programmeRepository.existsByNom(nouveauNom);

    }
  • I add @Component to my ProgrammeNomUnique.java

Question : I found a github project which works. I did exactly the same way but it was not working for me... The oly one difference, he used javax imports and i use jakarta imports. I cannot use javax because i'm using SB3, maybe they changed how it works... what do you think?

HERE there is my gitHub if you want to see and try with me -> https://github.com/RaphaelAMAMAM/temp-repo-for-validator

R Am
  • 11
  • 1
  • 2
  • Because it will be constructed with the default constructor and not the one that does injection. – M. Deinum Feb 21 '23 at 09:07
  • Thanks M. Deinum, it still does not work, i post my update just below. Could you tell me more about your idea please? – R Am Feb 21 '23 at 09:17
  • You do need to annotate your class as `@Component` (or `@Service`) for Spring to autowire (not sure if applicable for validators, but would be surprised if not). I would also recommend declaring the repository `final` and use `@RequiredArgsConstructor`. – daniu Feb 21 '23 at 09:21
  • Thanks daniu, I still have the same problem with your advice. Do you have another idea? – R Am Feb 21 '23 at 09:38
  • I did M. Deinum ! Sorry I'm not familiar with stackoverflow for now. All updates and questions are in my first post – R Am Feb 21 '23 at 13:30
  • YOur last one, why does it have a scope? Also there are no required parameters., so the `@RequiredArgsConstructor` doesn't do anything. As mentioned before make sure it is being picked up. You are linking to a repository but I see nowhere the validator is being used. – M. Deinum Feb 21 '23 at 15:28
  • It was because i tried others things but now i deleted it and it still does not work. My required parameters are in my entity Programme (here https://github.com/RaphaelAMAMAM/temp-repo-for-validator/blob/main/app-web-test/src/main/java/com/laramendez/appweb/entity/Programme.java) I don't edit my post to post him because i have this message (There are too many pending edits on Stack Overflow. Please try again later.) So, it seems I have my requiredArgsConstructor and my required parameters. Do you know what I can do more? Again thank you M. Deinum for your help – R Am Feb 21 '23 at 15:56

0 Answers0