I have implemented an enum validator following the older posts here. I was wondering whether this following code is thread safe or not? I have got many different enums for which I need to use this validator. Is this going to create any problems?
@Documented
@Constraint(validatedBy = StringEnumerationValidator.class)
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE,
ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@NotNull(message="Value must not be null.")
public @interface StringEnumeration {
String message() default "{com.xxx.bean.validation.constraints.StringEnumeration.message}";
Class<?>[] groups() default{};
Class<? extends Payload>[] payload() default{};
Class<? extends Enum<?>> enumClass();
}
public class StringEnumerationValidator implements
ConstraintValidator<StringEnumeration, String> {
private Set<String> AVAILABLE_ENUM_NAMES;
public static Set<String> getNamesSet(Class<? extends Enum<?>> e){
Enum<?>[] enums = e.getEnumConstants();
String[] names = new String[enums.length];
for (int i = 0; i < enums.length; i++) {
names[i] = enums[i].name();
System.out.println(enums.length);
System.out.println(enums[i]);
}
Set<String> mySet = new HashSet<String>(Arrays.asList(names));
return mySet;
}
@Override
public void initialize(StringEnumeration stringEnumeration) {
Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass();
AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected);
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
else {
return AVAILABLE_ENUM_NAMES.contains(value);
}
}
EDIT: Sources referred:
Yes and no. Strictly speaking, it is not thread safe, because your
initializemethod could be called concurrently by two different threads. This method writes to theAVAILABLE_ENUM_NAMESvariable, and thus the two threads might interfer with each other.But if you make sure that
initializeis called only once for each instance, before other threads have access to that instance, it is thread safe becauseisValidonly reads the set and does not modify it.To ensure that initializing is done only once, you should do it in the constructor:
and remove the
intializemethod.