I have following custom ConstraintValidator:
public class FileNamePatternValidator implements ConstraintValidator<FilenamePattern, FileUpload> {
String regex;
@Override
public void initialize(FilenamePattern constraintAnnotation) {
regex = constraintAnnotation.regex();
}
@Override
public boolean isValid(FileUpload fileUpload, ConstraintValidatorContext context) {
if (fileUpload == null) {
return true;
}
// Check if filename of fileUpload is correct
return true;
}
}
Now I was wondering if I put this FilenamePattern on a parameter inside a method like this
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("{xy}")
public Response saveXY(
@PathParam("xy")
String xy,
@RestForm("txtFile")
@FilenamePattern(regex = "^[a-zA-Z_\\.]+\\.txt$")
FileUpload txtFile
) {
// Do something with file
return Response.ok().build();
}
which can be called in parallel. Does this mean that I do not need to worry about thread safety of my ConstrainValidator. Because if jakarta ee handles ConstraintValidator inside container as singletons then field String regex;
is shared resource and I need to save regex value as ThreadLocal.
I think I solved this question. The answer is following:
Container creates a new instance of ConstraintValidator
per each specific type of annotation that’s used.
Since the annotation does not change in the runtime,
it means that we only create an instance of ConstraintValidator
only once for that specific annotation and only at that time do we call initialization()
method. Because of this, we do not care if isValid()
would be called from more threads, since fields that were set by the initialization method were called only for that specific annotation.
So, this means that we can implement ConstraintValidator as I did it and not worry for thread-safety.