user1154644 user1154644 - 6 months ago 13
Java Question

Java generics wildcard operator

I am trying to write a utility method to assist me with builing exception messages for any validation errors with respect to bean validation in my application. When I go to validate my object (in this case, BasicContactInformation) I do it as follows:

Set<ConstraintViolation<BasicContactInformation>> constraintViolations = validator.validate(basicContactInformation);
if(!CollectionUtils.isEmpty(constraintViolations)){
throw new CustomerAccountException(LoggingUtils.getLoggingOutput("Unable to update customer contact information", constraintViolations));
}


I am doing the same thing for other beans. The utility method will take in a prefix for the exception message, along with the set of constraint validations, and will build a nicely formatted output message. The problem is, I can't figure out how to build the message such that it can accept a set of constraint violations of any type. I tried the following, but it doesn't seem to be valid, as it says it cant cast:

public static String getLoggingOutput(String prefix, Set<ConstraintViolation<?>> violations){
StringBuilder outputBuilder = new StringBuilder(prefix);
if(!CollectionUtils.isEmpty(violations)){
for(ConstraintViolation<?> currentViolation: violations){
outputBuilder.append("[");
outputBuilder.append(currentViolation.getMessage());
outputBuilder.append("]");
}
}
return outputBuilder.toString();
}


This is the compiler error

The method getLoggingOutput(String, Set<ConstraintViolation<?>>) in the type LoggingUtils is not applicable for the arguments (String, Set<ConstraintViolation<BasicContactInformation>>)


Any idea as to what the method signature should be so that it would work for any set of constraint violations? I'm trying to avoid writing a method that takes in a set of constraint violations for foo, one for bar, one for baz, etc.

Answer

You can make the method generic:

public static <T> String getLoggingOutput(String prefix,
        Set<ConstraintViolation<T>> violations) {
    // ...
}

Under most circumstances, if not all, the compiler will infer the type parameter from the argument. This is not at all the same thing as using a wildcard.