I don't know Spring, however to understand some of the java patterns I was reading through Spring tutorials and stumbled onto below code. By the look of it, this looks like classic decorator, but then you see ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);. I am somewhat uncomfortable using utility to delegate to the other validator since I feel it would be difficult to unit test these static invocations(although it can be achieved with PowerMock but am not a big fan of the same). I feel addressValidator.validate() is pretty much cleaner.Since I am writing a custom validator for one my applications, I just wanted to get some thoughts on these approaches.
public class CustomerValidator implements Validator {
private final Validator addressValidator;
public CustomerValidator(Validator addressValidator) {
this.addressValidator = addressValidator;
}
public boolean supports(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
Customer customer = (Customer) target;
try {
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
} finally {
errors.popNestedPath();
}
}
}
Related
I am extending AbstractRepositoryEventListener in order to create a md5 hash of an photo and save it with the object.
I'd like to abort saving the photo altogether in the event of an exception.
#Component
public class MyHandler extends AbstractRepositoryEventListener<Photo> {
#Autowired
PhotoService photoService;
#Override
public void onBeforeSave(Photo photo) {
File originalPhoto = new File(foto.getUriOriginal());
try {
String hash = photoService.getHash(originalPhoto);
photo.setHash(hash);
} catch ( IOException | NoSuchAlgorithmException e ) {
e.printStackTrace();
}
}
}
You may throw an instance of RuntimeException. It will get Spring to rollback.
There are other more comprehensive ways, details of which you can find here.
If someone ever have this same problem, here's a better approach.
The goal here is basically to validate an entity.
Spring already provides a ValidatingRepositoryEventListener that uses validators to achieve this goal. Not only will the saving be "aborted", but also the error message will be provided to the client.
It is important to notice that automatic discovery of validators seem to have a bug with a workaround described here.
It is also possible to create custom validation annotations, as described in the link below, resulting in a more reusable code.
In this particular instance, the Validator would look something like this:
#Component("beforeSavePhotoValidator")
public class PhotoValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return Photo.class.equals(clazz);
}
#Override
public void validate(Object obj, Errors errors) {
if (customValidationIsInvalid(obj)){
errors.rejectValue(
"<invalidFieldName>",
"<errorMessageCode>"
);
}
}
}
Observe that:
customValidationIsInvalid, invalidFieldName and errorMessageCode should be appropriately implemented
the errorMessageCode must be set in the ValidationMessages.properties file
the workaround must be implemented, or the validator manually registered
I was thinking about a good implementation for validators. My service method starts like this:
if(badSituation()){
return Response.status(400).entity("bad situtaion").build();
}
if(badSituation2()){
return Response.status(400).entity("bad situtaion2").build();
}
...
if(badSituationN()){
return Response.status(400).entity("bad situtaionN").build();
}
Since validators multiply really fast I have decided to refactor them to some design pattern. I was thinking about Chain of Responsibility or Composite, however I had a problem with practical realization. Can someone suggest how this code should be refactored?
You can use the Cor Pattern for the validation "Behavior" : Each of your validators would implement a base ChainedValidator interface (some of the behavior can be moved to a parent abstract class as it is the same for all chain members):
public class MyFirstValidator implements ChainedValidator{
//This CoR implementation has also a 'Composite' background
ChainedValidator nextValidator;
#Override
private void doValidate(Request request) throws ValidationException
{
if(badSituation){
//throw validation exception
}
}
#Override
public void doChainValidate(Request request) throws ValidationException
{//This method can be moved to a parent abstract class
doValidate(request);
if(nextValidator!=null){
nextValidator.doChainValidate(request);
}
}
private void attachValidator(ChainedValidator newValidator) throws ValidationException
{//same as previous method
if(nextValidator!=null){
nextValidator.attachValidator(request);
}else{
nextValidator=newValidator;
}
}
//setters & other methods
}
On your Controllers/Web tier Service classes, you can inject the first ChainedValidator of the validation chain and call doChainValidate :
public class WebTierService{
ChainedValidator validator;
public Response serviceMethod(Request request){
try{
//...
validator.doChainValidate(request);
//...
}catch(ValidationException e){
return Response.status(400).entity(e.getMessage()).build();
}
}
}
As you can see, the logic is 'fluid' (No if else check depending on type of validation error) and adding a new validator is relatively simple (validator.attachValidator()) which makes the logic extensible and clean.
I am writing a library which is used for validating some specific objects.
I implemented it like strategy pattern.
What is the best pattern for implementing a validation library ?
Some of my code is shown below.
//INTERFACE
public interface IValidator {
public boolean validate(Object o) throws ValidationException;
}
//VALIDATOR OBJECT
public class Validator {
private IValidator validator;
public Validator(IValidator validator)
{
this.validator=validator;
}
public boolean validate(Object o) throws ValidationException
{
return this.validator.validate(o);
}
}
//EMAIL VALIDATOR
public class EmailValidator implements IValidator{
#Override
public boolean validate(Object o) throws ValidationException {
//VALIDATE E MAIL HERE
return false;
}
}
//TEST RUN
Validator validator = new Validator(new EmailValidator());
validator.validate("some email");
I guess the answer to this question is mainly subjective so I can only give my own opinion:
I myself use the strategy pattern as well for such tasks because that is what it is meant for. You use a specific validation strategy depending on the input of the function so the strategy pattern is alright, I think.
Read the first part of the Wiki article about the strategy pattern Strategy Pattern. Their main example is also about validation.
I would enhance your code as below:
//INTERFACE
public interface IValidator<T> {
void validate(T arg) throws ValidationException;
}
//EMAIL VALIDATOR
public class EmailValidator implements IValidator<Email email>{
#Override
public void validate(Email email) throws ValidationException {
//VALIDATE E MAIL HERE, throw exception, if needed
}
}
// Usage
EmailValidator validator = new EmailValidator();
validator.validate(); // Catch ValidatorException here to transform into business exception and appropriate error handling
Few points:
Here java Type Eraser can help implement IValidator interface with any custom implementation.
Validation logic is outside POJO, POJO is pure POJO :)
I'm looking to combine the flexibility of Spring Profiles and Configurations with the parallel running of JUnit tests which utilize either the Parameterized or Theories annotation. Is there any way to incorporate all of these features to get my unit tests running?
The problem I keep running into is the parameters need access to an injected bean, which isn't possible since the function annotated with #Parameters or #DataPoints is supposed to be static. I'd really hate to have to wire that into each class or even a static function somewhere because I'd like to quickly be able to switch profiles without having to change Java code. Is this possible?
Found the ticket for this request. It seems the attached file has some issues though. Looks like it's been a feature request for quite some time now.
I've been looking for a solution of this problem too. And there is one ! But as it comes from somebody's blog, I can't take the credit for it however. :-)
Unfortunately I can't find the original blog any more...
#RunWith(Parameterized.class)
#ContextConfiguration("/beans.xml")
public class MyTest {
private final File file;
public MyTest(final File file) {
this.file = file;
}
#Autowired
private PlatformTransactionManager transactionManager;
private TestContextManager testContextManager;
#Parameterized.Parameters
public static Collection<File[]> getFilesToTest() throws Exception {
return getValidFiles();
}
#Before
public void setUpSpringContext() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this); // does the autowiring !
}
#Test
public void testInTransactionContext() throws Exception {
new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status) {
status.setRollbackOnly();
try {
... run the test ...
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
});
}
}
I've got a fairly standard Spring webapp, and I have a number of custom annotations that I would like to use to denote the requirements and constraints applied to a given web-service method. For instance, I might apply an #RequiresLogin annotation to any method that requires a valid user session, and #RequiresParameters(paramNames = {"name", "email"}) on a method that requires that "name" and "email" be set, and so on.
In support of this I implemented an ad-hoc utility for validating a method's annotated constraints at runtime, which basically followed a pattern of:
Map<Class<? extends Annotation>, Annotation> annotations = mergeConstraintsFromClassAndMethod(serviceClass, serviceMethod);
if (annotations.containsKey(AnnotationType1.class)) {
AnnotationType1 annotation = (AnnotationType1)annotations.get(AnnotationType1.class);
//do validation appropriate to 'AnnotationType1'
}
if (annotations.containsKey(AnnotationType2.class)) {
AnnotationType2 annotation = (AnnotationType2)annotations.get(AnnotationType2.class);
//do validation appropriate to 'AnnotationType2'
}
//...
This works fine, but has become a bit unwieldy as I have added additional annotations. I'd like to replace it with something a bit more maintainable. Ideally I'd like to be able to do:
List<ValidatableAnnotation> annotations = mergeConstraintsFromClassAndMethod(serviceClass, serviceMethod);
for (ValidatableAnnotation annotation : annotations) {
annotation.validate(request);
}
But I'm pretty sure that is not possible since annotations themselves cannot contain executable code and since the compiler will not let me extend java.lang.annotation.Annotation (not that I'd know how to go about allowing executable code to be contained in an annotation even if the compiler let me try).
What annotations can contain, however, is a nested inner class, and that inner class can do anything that a normal Java class can do. So what I've come up with based upon that and in the interest of keeping my validation code as closely associated with the annotation being validated as possible is:
public interface AnnotationProcessor {
public boolean processRequest(Annotation theAnnotation, HttpServletRequest request);
}
And then the annotations can be implemented like:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface RequiresLogin {
public static class Processor implements AnnotationProcessor {
#Override
public boolean processRequest(Annotation theAnnotation, HttpServletRequest request) {
if (! (theAnnotation instanceof RequiresLogin)) {
//someone made an invalid call, just return true
return true;
}
return request.getSession().getAttribute(Constants.SESSION_USER_KEY) != null;
}
}
}
Which keeps the validation logic nice and tightly coupled with the annotation that is being validated. Then all my ad-hoc validation code can be replaced with:
List<Annotation> annotations = mergeConstraintsFromClassAndMethod(serviceClass, serviceMethod);
for (Annotation annotation : annotations) {
processAnnotation(annotation, request);
}
private static boolean processAnnotation(Annotation annotation, HttpServletRequest request) {
AnnotationProcessor processor = null;
for (Class<?> processorClass : annotation.annotationType().getDeclaredClasses()) {
if (AnnotationProcessor.class.isAssignableFrom(processorClass)) {
try {
processor = (AnnotationProcessor)processorClass.newInstance();
break;
}
catch (Exception ignored) {
//couldn't create it, but maybe there is another inner
//class that also implements the required interface that
//we can construct, so keep going
}
}
}
if (processor != null) {
return processor.processRequest(annotation, request);
}
//couldn't get a a processor and thus can't process the
//annotation, perhaps this annotation does not support
//validation, return true
return true;
}
Which leaves no more ad-hoc code that needs to be revised every time I add a new annotation type. I just implement the validator as part of the annotation, and I'm done.
Does this seem like a reasonable pattern to use? If not then what might work better?
You may want to investigate AOP. You can advise methods that expose certain annotations and perform pre/post processing accordingly.
I would just like to add that while AOP would be a good solution, the Spring framework already provides this functionality by way of the #Secured annotation.
#Secured("ROLE_USER")
public void foo() {
}
Spring also supports JSR-303 validation with the #Valid annotation. So for these use cases at least, it seems you are re-inventing the wheel.
IMHO one could think about the Visitor pattern in combination with a factory. The factory will return a wrapper object that knows the exact annotation type and which the visitor will be able...
class MyVisitor {
public void visit(VisitableAnnotationType1 at) {
//something AnnotationType1 specific
}
public void visit(VisitableAnnotationType2 at) {
//something AnnotationType2 specific
}
... // put methods for further annotation types here
}
class VisitableFactory {
public abstract class VisitableAnnotation {
public abstract void accept(MyVisitor visitor);
}
class VisitableAnnotationType1 implements VisitableAnnotation {
public void accept(MyVisitor visitor) {
visitor.visit(this);
}
}
public static VisitableAnnotation getVisitable(Annotation a) {
if(AnnotationType1.class.isAssignableFrom(a.getClass()) {
//explicitely cast to the respective AnnotationType
return new VisitableAnnotationType1((AnnotationType1)a);
} else if (AnnotationType2.class.isAssignableFrom(a.getClass()) {
//explicitely cast to the respective AnnotationType
return new VisitableAnnotationType1((AnnotationType1)a);
}
}
}
As we cannot extend Annotation, we need those wrapper classes in the factory. You could also pass the original annotation which is then contained in that wrapper class.
What you have to do: For each new AnnotationType add a new "wrapper" class to the factory, extend the factory's
getVisitable()
method accordingly and also add an according method to the Visitor:
public void doSomething(VisitableAnnotationTypeXYZ at) {
//something AnnotationTypeXYZ specific
}
now the generic validation (or whatever) code looks like:
List<ValidatableAnnotation> annotations = mergeConstraintsFromClassAndMethod(serviceClass, serviceMethod);
MyVisitor visitor = new MyVisitor();
for (ValidatableAnnotation annotation : annotations) {
VisitableFactory.getVisitable(annotation).accept(visitor);
}
The visiting works by the indirection that the visited object calls the visitor with itself as the argument and thus the correct visit method will be invoked.
Hope that helps ;-)
Code is not tested, though...