I've got stuck on a problem with a custom annotation I created for a while now in my Micronaut REST app. What I need my annotation to do is: read the value of a boolean field in my record class and if it is true activate the validation.
So, if isCompany
is set to true then I want to make it so that annotated fields are not null, if set to false these annotated fields can be null.
My current code works however, the "true" value is hardcoded and I can't find a way to pass the value while making a POST.
Is there a way I can do it?
Custom annotation package:
package com.app.annotations.messages;import io.micronaut.context.StaticMessageSource;import jakarta.inject.Singleton;@Singletonpublic class ValidateCompanyMessages extends StaticMessageSource { public static final String COMPANY_MESSAGE = "must not be null"; public ValidateCompanyMessages() { addMessage("com.app.ValidCompany.message", COMPANY_MESSAGE); }}
package com.app.annotations.utils;public final class ValidateCompanyUtil { private ValidateCompanyUtil() { } public static boolean isValid(Boolean isCompany, Object value) { if (isCompany != null && isCompany) { if (value == null || value.toString().trim().isEmpty()) { return false; } } return true; }}
package com.app.annotations.validators;import com.app.annotations.ValidCompany;import com.app.annotations.utils.ValidateCompanyUtil;import io.micronaut.context.annotation.Factory;import io.micronaut.validation.validator.constraints.ConstraintValidator;import jakarta.inject.Singleton;@Factoryclass ValidateCompanyFactory { @Singleton ConstraintValidator<ValidCompany, String> companyValidator() { return (value, annotationMetadata, context) -> ValidateCompanyUtil.isValid(true, value); }}
package com.app.annotations;import jakarta.validation.Constraint;import jakarta.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Repeatable;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER, ElementType.TYPE_USE })@Retention(RetentionPolicy.RUNTIME)@Documented@Repeatable(ValidCompany.List.class)@Constraint(validatedBy = {})public @interface ValidCompany { String MESSAGE = "com.app.ValidCompany.message"; String message() default "{" + MESSAGE +"}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER, ElementType.TYPE_USE }) @Retention(RetentionPolicy.RUNTIME) @Documented @interface List { ValidCompany[] value(); }}
Record class:
package com.app.records;import java.time.LocalDateTime;import java.util.UUID;import com.app.annotations.ValidCompany;import io.micronaut.data.annotation.AutoPopulated;import io.micronaut.data.annotation.Id;import io.micronaut.data.annotation.MappedEntity;import io.micronaut.serde.annotation.Serdeable;import jakarta.annotation.Nullable;import jakarta.validation.constraints.NotNull;@Serdeable@MappedEntity("request")public record RequestRecord( @Id @AutoPopulated UUID id, @NotNull String title, @NotNull String description, @NotNull String notes, @NotNull String firstName, @NotNull String lastName, @NotNull String email, @NotNull String phone, @NotNull String residence, @NotNull String taxCode, @ValidCompany String invoiceHolder, @ValidCompany String vatCode, @Nullable String sdiCode, @ValidCompany String companyAddress, @ValidCompany String city, @ValidCompany String zipCode, @ValidCompany String province, @ValidCompany String country, @ValidCompany String companyPhone, @ValidCompany String companyEmail, @NotNull Boolean isCompany) {}