Wednesday, July 31, 2013

Spring MVC : How to perform validation ?

With Spring MVC, there are 3 different ways to perform validation : using annotation, manually, or a mix of both. There is not a unique "cleanest and best way" to validate, but there is probably one that fits your project/problem/context better.
Let's have a User :
public class User {

    private String name;

    ...

}
Method 1 : If you have Spring 3.x+ and simple validation to do, usejavax.validation.constraints annotations (also known as JSR-303 annotations).
public class User {

    @NotNull
    private String name;

    ...

}
You will need a JSR-303 provider in your librairies, like Hibernate Validator who is the reference implementation (this library has nothing to do with databases and relational mapping, it just does validation :-).
Then in your controller you would have something like :
@RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, @Valid @ModelAttribute("user") User user, BindingResult result){
    if (result.hasErrors()){
      // do something
    }
    else {
      // do something else
    }
}
Notice the @Valid : if the user happens to have a null name, result.hasErrors() will be true.
Method 2 : If you have complex validation (like big business validation logic, conditional validation across multiple fields, etc.), or for some reason you cannot use method 1, use manual validation. It is a good practice to separate the controller’s code from the validation logic. Don't create your validation class(es) from scratch, Spring provides a handy org.springframework.validation.Validatorinterface (since Spring 2).
So let's say you have
public class User {

    private String name;

    private Integer birthYear;
    private User responsibleUser;
    ...

}
and you want to do some "complex" validation like : if the user's age is under 18, responsibleUser must not be null and responsibleUser's age must be over 21.
You will do something like this
public class UserValidator implements Validator {

    @Override
    public boolean supports(Class clazz) {
      return User.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
      User user = (User) target;

      if(user.getName() == null) {
          errors.rejectValue("name", "your_error_code");
      }

      // do "complex" validation here

    }

}
Then in your controller you would have :
@RequestMapping(value="/user", method=RequestMethod.POST)
    public createUser(Model model, @ModelAttribute("user") User user, BindingResult result){
        UserValidator userValidator = new UserValidator();
        userValidator.validate(user, result);

        if (result.hasErrors()){
          // do something
        }
        else {
          // do something else
        }
}
If there are validation errors, result.hasErrors() will be true.
Note : You can also set the validator in a @InitBinder method of the controller, with "binder.setValidator(...)" (in which case a mix use of method 1 and 2 would not be possible, because you replace the default validator). Or you could instantiate it in the default constructor of the controller. Or have a @Component/@Service UserValidator that you inject (@Autowired) in your controller : very useful, because most validators are singletons + unit test mocking becomes easier + your validator could call other Spring components.
Method 3 : Why not using a combination of both methods? Validate the simple stuff, like the "name" attribute, with annotations (it is quick to do, concise and more readable). Keep the heavy validations for validators (when it would take hours to code custom complex validation annotations, or just when it is not possible to use annotations). I did this on a former project, it worked like a charm, quick & easy.
Warning : you must not mistake validation handling for exception handlingRead this post to know when to use them.
References :

Friday, July 26, 2013

Java EE Security Realms

A realm is a credential store that enables identity or role based access control.
What is a realm?
For a web application, a realm is a complete database of users and groups that identify valid users of a web application (or a set of web applications) and are controlled by the same authentication policy.
The Java EE server authentication service can govern users in multiple realms. In this release of the Application Server, the file, admin-realm, and certificate realms come preconfigured for the Application Server.
In the file realm, the server stores user credentials locally in a file named keyfile. You can use the Admin Console to manage users in the file realm.
When using the file realm, the server authentication service verifies user identity by checking the file realm. This realm is used for the authentication of all clients except for web browser clients that use the HTTPS protocol and certificates.
In the certificate realm, the server stores user credentials in a certificate database. When using the certificate realm, the server uses certificates with the HTTPS protocol to authenticate web clients. To verify the identity of a user in the certificate realm, the authentication service verifies an X.509 certificate. For step-by-step instructions for creating this type of certificate, see Working with Digital Certificates. The common name field of the X.509 certificate is used as the principal name.
The admin-realm is also a FileRealm and stores administrator user credentials locally in a file named admin-keyfile. You can use the Admin Console to manage users in this realm in the same way you manage users in the file realm. For more information, see Managing Users and Groups on the Application Server.
http://stackoverflow.com/questions/9311353/java-ee-security-realms

Wednesday, July 24, 2013

The appendReplacement and appendTail

appendReplacement and appendTail are the methods that do the real work when you call replaceAll. Each time a match is found in the input, appendReplacement appends to the output all the text between the previous match and the current one, then it appends the replacement text. appendReplacement is also the method that processes the replacement text, converting $1, $2, etc. to the corresponding captured groups. When there are no more matches, appendTail appends whatever's left of the input (whatever followed the last match).

You use appendReplacement and appendTail directly when you want to process the input in some other--or additional--manner than replaceAll does. For instance, if you want to use the matched text as a key to look up the replacement value in a table, you have to write your own replaceAll equivalent. Here's an example I happened to have handy:
view plaincopy to clipboardprint?
  1. import java.util.*;  
  2. import java.util.regex.*;  
  3.    
  4. class Test  
  5. {  
  6.   static Map props = new HashMap();  
  7.   static  
  8.   {  
  9.     props.put("key1""fox");  
  10.     props.put("key2""dog");  
  11.   }  
  12.    
  13.   public static void main(String[] args)  
  14.   {  
  15.     String input = "The quick brown ${key1} jumps over the lazy ${key2}.";  
  16.    
  17.     Pattern p = Pattern.compile("\\$\\{([^}]+)\\}");  
  18.     Matcher m = p.matcher(input);  
  19.     StringBuffer sb = new StringBuffer();  
  20.     while (m.find())  
  21.     {  
  22.       m.appendReplacement(sb, "");  
  23.       sb.append(props.get(m.group(1)));  
  24.     }  
  25.     m.appendTail(sb);  
  26.     System.out.println(sb.toString());  
  27.   }  
  28. }  

Monday, July 22, 2013

how to use tag in strut 1.2?

Javadoc for :
Specifies the attribute name of the bean whose property is accessed to retrieve the value specified byproperty (if specified). If property is not specified, the value of this bean itself will be rendered.
In essence, if you have a JavaBean (with getters and setters),
Person person = new Person;
request.setAttribute("person", person);
by setting , you're telling Struts to first findperson object first from PageContext scope. If not found, then request, then session, thenapplication scope.
The property="age" attribute (from  tag), will then call the getter methodgetAge() from the Person object (irrespective of whether there's an instance variable called ageon the bean).
Hope this helps.

Wednesday, July 10, 2013

Physical or Logical Delete of Database Record

Advantages are that you keep the history (good for auditing) and you don't have to worry about cascading a delete through various other tables in the database that reference the row you are deleting. Disadvantage is that you have to code any reporting/display methods to take the flag into account.
As far as if it is a common practice - I would say yes, but as with anything whether you use it depends on your business needs.
EDIT: Thought of another disadvantange - If you have unique indexes on the table, deleted records will still take up the "one" record, so you have to code around that possibility too (for example, a User table that has a unique index on username; A deleted record would still block the deleted users username for new records. Working around this you could tack on a GUID to the deleted username column, but it's a very hacky workaround that I wouldn't recommend. Probably in that circumstance it would be better to just have a rule that once a username is used, it can never be replaced.)