Announcement Announcement Module
Collapse
No announcement yet.
Validation concept questions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Validation concept questions

    Hello,

    Im working on project where we use JSF in combination with Spring.

    As we have custom validators for JSF i had the idea to decouple the validation from JSF, as some validations like Zip-Code etc. could be used later in some service classes, which won't have a user interface.

    As a result of my brainstorming, the following structure would be needed

    This would be the pojo-validator-interface
    Code:
    public interface Validator{
        public abstract void validate(Object o) throws ValidationException;
    }
    The pojo-validator itself
    Code:
    public ZipCodeValidator implements Validator{
        public void validate(Object o) throws ValidationException{
           // validation code
         }
    }

    Now to be able to use my pojo in a custom JSF validator the following code would be written. The idea is that the validate method in the JSF-validator just delegates the code to my pojo, so that i have a central pojo-based validator that could be used also out of the JSF context.

    Code:
    import javax.faces.validator.Validator;
    
    
    public class MyValidator implements Validator {
    
    
    public void validate(FacesContext ctx, UIComponent uic, Object o)
    		throws ValidatorException {
    	// retrieve the validator from the BeanFactory
            try{
            myPojoValidator.validate(o);
    	}catch(ValidatonException e){
                  throw new ValidatorException("Oooops it went wrong");
            }	
    }
    }
    What do you guys think about this concept?

  • #2
    I think you're on the right track. It is always good to delegate the responsibilities to a separate object or layer.

    To my understanding, your POJO validation interface and implementation(s) would reside at the domain layer (along with the rest of the business rules). What I might add to this are:
    1. Since javax.faces.validator.Validator already exists, perhaps your POJO validation interface should be renamed to, say, CustomValidator. This helps to avoid any conflicts.
    2. Perhaps it would be useful to define your own RuntimeException instead of explicity throwing back ValidationException. This will help make Service implementations much easier in future. Using RuntimeExceptions offers flexibility over change in your implementation (for example, you don't have to explicity define at the method signature of what exceptions are to be thrown).
    As we have custom validators for JSF i had the idea to decouple the validation from JSF, as some validations like Zip-Code etc. could be used later in some service classes, which won't have a user interface.
    A brilliant way to handle decoupling is to have a Service layer (http://martinfowler.com/eaaCatalog/serviceLayer.html). I notice that you mention about 'service classes', which I assume would represent something like web services so that other applications can integrate with this application. This would be your Integration Gateway layer (or to cut it short, the Integration layer). All of the integration implementations would go here (be it web service, RMI, etc.).

    With regards to the Service layer, these are coarse grained implementations that represent specific business tasks. In this case, the Service layer implementation would be:

    Code:
    package org.myapp.service;
    
    public interface ValidatorService {
    
        abstract void validateZipCode(Object o);
    
        abstract void validateAnother(Object o);
    
        ..
    }
    Code:
    package org.myapp.service.standard;
    
    import org.myapp.domain.validator.CustomValidator;
    import org.myapp.domain.validator.ZipCodeValidator;
    
    public StandardValidatorService implements ValidatorService {
    
        public void validateZipCode(Object o) {
           CustomValidator zipCodeValidator = null;
           ..
           zipCodeValidator = new ZipCodeValidator();
           zipCodeValidator.validate(o);
           ..
        }
    
        public void validateAnother(Object o) {
           ..
        }
        ..
    }
    At the JSF (user interface) level, adapting to your implementation, the following is applied:

    Code:
    package org.myapp.application.userinterface;
    
    import javax.faces.validator.Validator;
    
    import org.myapp.service.ValidatorService;
    
    public class MyValidator implements Validator {
    
    private ValidatorService validatorService; // Either use dependency injection, or... .. public void validate(FacesContext ctx, UIComponent uic, Object o) throws ValidatorException { // ..retrieve the StandardValidatorService from the BeanFactory try{ this.validatorService.validateZipCode(o); }catch(CustomValidatonException e){ throw new ValidatorException("Oooops it went wrong", e); } }
    }
    Although there is a slight overahead in terms additional coding, which may seem unnecessary, the benefits outweighs. Any changes to the validation rules does not directly affect the JSF implementations, and vice versa. Also, it would be possible to manage transactions (inc. distributed), exceptions, workflow and logging more effectively.

    It would be easy to expose this Service layer implementation directly, but preferably such implementation should be done at the Integration layer to control what implementations needs to be exposed.

    I hope this answers your question.

    Comment


    • #3
      Thanks a lot for your valuable answer :-)

      I build up the whole architecture with the structure you mentioned. For validators however i tried to decouple them as much as i can and didnt want to put them into general Validator Service's.

      At the moment most of the syntax checks on a form are made in the JSF layer.
      So, having the custom validators delegating the job to my pojo-validators does the job.

      As soon as i see the usecase to have validations on service level, i can just create the services you mentioned and delegate the validation to my custom validator.

      That would be the best approach i think. What do you think?

      Comment


      • #4
        You'll still have the flexibility to have as many custom validators when they are kept in the Domain layer. The Application layer (the JSF user interface implementation) will have access to all of the custom validators that are held in the domain layer via the ValidatorService.

        Remember the Service layer is course grained, meaning that you'll have many methods in each Service implementation.

        So, in this case, there will be one CustomValidator interface with many implementations from this:
        Interface:
        org.myapp.domain.validator.CustomValidator

        That implements CustomValidator:
        org.myapp.domain.validator.ZipCodeValidator
        org.myapp.domain.validator.EmailValidator
        org.myapp.domain.validator.DateOfBirthValidator
        org.myapp.domain.validator.RegistrationValidator
        ..
        .. and so on...
        Then you have a single ValidatorService:
        Interface:
        org.myapp.service.ValidatorService
        that will have the following methods:

        abstract void validateZipCode(Object o);
        abstract void validateEmail(Object o);
        abstract void validateDateOfBirth(Object o);
        abstract void validateRegistration(Object o);
        ..
        .. and so on...
        That implements ValidatorService:
        org.myapp.service.standard.StandardValidatorServic e


        As the application grows or requires change in future it is possible to extend the ValidatorService to minimise the interruption between the Application and Domain layers. For example:
        Interface:
        org.myapp.service.ExtendedValidatorService
        that extends from org.myapp.service.ValidatorService interface, and also includes:

        abstract void validateAddress(Object o);
        abstract void validateUrl(Object o);
        ..
        .. and so on...
        That implements ExtendedValidatorService:

        org.myapp.service.standard.StandardExtendedValidat orService

        Of course, depending on the size of the application it is possible to divide the Services implementation where appropriate (but try keeping it as a few). For example:

        OrderValidatorService
        RegistrationValidatorService
        SupplierValidatorService


        Hope this helps.

        Comment


        • #5
          thx a lot for your ideas...i already took the mix of bot ideas and did and implementation that works just fine :-)

          Comment


          • #6
            Validation should not throw an exception to indicate that validation failed. An exception indicates an 'exceptional' condition, not normal and expected workflow (it is pretty common for an object to fail validation, especially in the web tier).

            Your validator should return a boolean indicating success/failure of validaton or you should have some kind of errors/result object that can be queried.

            Comment


            • #7
              i dont think that this is that easy...

              Such an argumentation would make everything but unchecked exceptions totaly useless...

              A Business Exception is catched by a developer, by knowing that it can happen...and it can happen often...

              Comment


              • #8
                Originally posted by uenluena View Post
                i dont think that this is that easy...

                Such an argumentation would make everything but unchecked exceptions totaly useless...

                A Business Exception is catched by a developer, by knowing that it can happen...and it can happen often...
                It certainly IS that easy. You are confusing the PURPOSE of exceptions.

                This is the architecture forum and fundamental architectural principles state that you DO NOT use exceptions for control flow.

                There is a lengthy thread about it here:

                http://stackoverflow.com/questions/7...w-an-exception

                And another discussion here:

                http://www.javapractices.com/topic/T...tion.do?Id=129

                I could dig up dozens more that all say the same thing. It is POOR design to use exceptions for control flow....PERIOD.

                As to your validation example specifically, look at ALL THE OTHER validation frameworks. Do any of them throw exceptions to indicate a validation failure?

                Here's just two examples....

                Commons Validator
                Code:
                class Validator
                {
                    ....
                    public ValidationResult validate()
                    {
                        ...
                    }
                }
                Spring MVC Validator
                Code:
                interface Validator
                {
                    public void validate(Object obj, Errors errors);
                }

                Comment


                • #9
                  why are you talking about control flow? non of us was talking about control flow...

                  I read more then enough sources about exception handling....there's not many topics in java that are more contraversial, then exception handling...

                  I dont share your opinion on this and think that it's a valid approach when JSF itself is catching a ValidatorException...So in any case i have to throw a ValidatorException...

                  You can also question their approach but then we start a religous discussion which i surely want to avoid in my thread

                  Comment


                  • #10
                    why are you talking about control flow? non of us was talking about control flow...

                    I read more then enough sources about exception handling....there's not many topics in java that are more contraversial, then exception handling...

                    I dont share your opinion on this and think that it's a valid approach when JSF itself is catching a ValidatorException...So in any case i have to throw a ValidatorException...

                    You can also question their approach but then we start a religous discussion which i surely want to avoid in my thread

                    Comment


                    • #11
                      uenluena,

                      I think it is worth revisiting this design of using exceptions for validators. In this case, I looked further into chudak comments. I understand that Exceptions to have an impact on performance compared to, say, raising flags or managing error codes.

                      Initially I understood that returning true and false for error handling was limit. Using error codes helped to distinguish the type of error, offering the flexibility to determine the type of error. But then there is the overhead to manage those codes, making it difficult to debug with and requires constant updates on the list of codes. Hence Exceptions was introduced as an alternative.

                      Looking at Spring Validator and Commons Validator, it seems that they have steered away from Exceptions when performing validation (for Spring MVC, Struts, etc.). Sounds like performance was a concern then.

                      However, what I did notice other implementations on how exceptions were used. Take Spring Security. That indeed throws exceptions back when there are issues with logging in. For example, there is org.acegisecurity.BadCredentialsException thrown when the credentials specified are invalid. Is there a performance concern here? Perhaps the difference here is that we're dealing with validation for authenticity, and not form fields.

                      But looking at JSF's validator it looks like it expects the ValidatorException to be thrown. I did notice some examples where the javax.faces.validator.Validator interface wasn't used and a custom validator that returns a boolean was used instead (http://www.roseindia.net/jsf/JSFLogi...lidation.shtml). Perhaps this is one way to avoid the use of exceptions.

                      The next question I have is within the Domain layer, do we use unchecked exceptions (RuntimeExceptions) within the business rules, or use validators?

                      (This is what I like about these forums is that it keeps you thinking and help improve.)

                      Comment


                      • #12
                        thanks again for your input shahnawazshahin :-) really enjoy reading your input

                        I also thought about what chudak wrote and im get several thoughts about that...

                        I really think that it depends where you try to catch those exceptions..

                        If you take JSF as example, it's indeed wrong in my point of view that at the closest layer to user input it catches ValidationExceptions. This exception is catched in the Web Layer, where its true that such a validation exception can occur quiet often, as there's a human being sitting behind the UI and knows from the normal web experience, that he can retype the same stuff 10 x wrongly and will still be able to retry etc...there the cost of such an Exception is quiet high.

                        When you however make this more granular structure and have, like in my structure a generic pojo validator, that can be used at different layers it makes sense that this validator raises an exception. But then again we have to ask us if it makes sense that we throw checked exceptions, as the lower we get, the less an user input can really recover from that error.

                        Comment


                        • #13
                          uenluena,

                          I generally agree with chudak on the issue - with some comments (see below), and I would advise you to consider his point. (You certainly don't have to, but since this forum is for architectural discussions, it's worth stressing the importance of the better ways of doing things.) Generally, an exception must only be thrown by a module if the module may not perform the expected functionality with the provided data. The rest of the decisions should be left up to the module's consumer. This gives the consumer the opportunity to interpret any validation results according to its own requirements. Let's take your example of the zip code validation. What are you trying to validate? If I were you, I'd use a ZipCode domain class that would itself prevent a construction of its instances with any data that under any circumstances may not be interpreted as a zip code. This will not include an empty string. Why? Because, many applications, under different circumstances, may tolerate an empty zip code. On the other hand, there is no point in allowing for creation of an instance of the class that can never be in a valid state. The constructor or set methods may invoke the validation logic that matches the input string against a zip regular expression. If the match fails, it is appropriate to throw a run-time exception. If you are using Spring, that exception will be caught during the binding attempt - on method invocation - and an error object will be created for the field. Or you can, handle it which ever way you want. Now, if the user did not enter anything in the field, you should allow creating an instance of ZipCode with an empty code in it, and pass it to the dedicated _application-specific_ validator. It is up to you to implement the validator to reject or allow an empty zip code. Now, you can implement an additional - generic (not application-specific) service) - that checks the provided zip code for being an actual US zip code. The reference to that service, in that case, should be injected in your app-specific validator. Again, the service should not impose an exception on your application. Just return false. Let the application (app-specific validator) decide whether it wants to throw an exception or simply add a new error object to the list of the errors passed to the page. I assume, you would want to do the latter, so the exception thrown by the service is just a very inconvenient burden on your app validator that now needs to catch it and translate into the error object.

                          The conclusions:

                          1) it's ok to throw an exception (RTE!) when attempting to construct an object with data that guarantees to render the instance invalid under any circumstances, or when a service is absolutely not capable to perform the requested operation with the provided data;

                          2) Different types of validation belong in different layers. A generic service (that is intended to be used by multiple applications and modules) must not throw exceptions based on the assumption that the result of the service API call is not acceptable to the caller. Different clients of this service may have different levels of tolerance to the seemingly exceptional conditions. To solve the problem, introduce a shared domain object that transports the result information from the service to the client. The Spring's Errors object is one example. But you can use any type of your domain model class to convey the service call results. For example, you can have an enum AccountStatus type that will be part of the Account instance returned by the AccountService.createNewAccount(...) call. If the account could not be created due to the "Account already exists" condition, the status will indicate that, and the rest of the fields won't be populated on the returned object. The client will inspect it and act accordingly. Sure, countless applications would rather throw some AccountAlreadyExistException - usually a checked one too! - and I think it is just wrong. People talk about SOA all the time and claim that they use it, but, in reality, I most often see architectures that are very app-specific, where services are tied to a particular application and can't be reused for other applications even within the same enterprise. (Well, that's also due to unfortunate and very common module packaging strategy when classes are grouped not according to their functionality but by type, e.g. the ".service" package hosts all services and therefore individual services can't be extracted and distributed separately; instead services should be packaged separately and include the service-specific domain and API under the same roof. But that's another topic...) Anyway, the point is: you always give the client the opportunity to decide for itself instead of imposing a potentially incorrect decision on it.

                          As far as checked exceptions are concerned, I am afraid, you are a bit behind on this one... The debate is over. Not everyone has received the memo, sadly...
                          Last edited by constv; Nov 19th, 2008, 03:23 PM.

                          Comment


                          • #14
                            hello,

                            Thanks a lot for you input too constv :-) your and chudaks remarks did for sure make me think about the validation exception issue.

                            Most of your remarks really made me think about the concept and the first thing i will do tomorrow is to check how i can implement those changes as it wont have a big impact at this state of the project.

                            Thanks again to everyone replied to this thread :-)

                            Comment


                            • #15
                              To make me summarize it:

                              -My pojo validator is a generic validator that should not decide if thats an exception or not. It just validates and gives back a status.

                              -The application/use case specific validator however, which is in my case the JSF Validator class, can, or even must throw a ValidationException as the JSF internal classes are catching this one to show an error message.

                              In the usage of my validators, where it's used in the JSF context only and directly in the JSP page with the EL possibilities like this one:

                              <h:inputText id="zipCode" value="#{myMbean.zipCode}">
                              <f:validator validatorId="myapp.zipCodeValidator"/>
                              </h:inputText>

                              there's not service class in between.

                              If i would validate in a service class, i would get my specific pojo validator, get my status and react according my use case by throwing a unified business exception to the JSF/gui/web service or give back again a status etc.

                              How does that sound to you guys?

                              Comment

                              Working...
                              X