JSR 303 - Bean Validation with OpenJPA - Part III

on July 25, 2011 0 comments
      
In the previous article, we have seen custom constraints. In this article we will see about validation groups.

Validation Groups:
Bean validation uses validation groups to determine what and when validation occurs. A validation group contains one or more constraints. There are no special interfaces to implement or annotations to apply in order to create a validation group. A validation group is denoted simply by a class definition. However, it is strongly recommended that simple interfaces are used. This is a best practice since it makes validation groups more usable in multiple environments. Whereas, if a class or entity definition were used as a validation group, it may pollute the object model of another application by bringing in domain classes and logic that do not make sense for the application. By default, if a validation group or multiple groups is not specified on an individual constraint, it will be validated using the javax.validation.groups.Default group.

Another advantage with validation groups is, instead of validating all the constraints at once, it will validate one group after the other, it will stop validation if one group couldn't be validated successfully.

Let's see how it can be implemented,
package com.sample.bean;

import java.util.Date;
import javax.validation.constraints.Future;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Book {

 @NotNull(groups = BookNotNull.class, message="Book Name should not be null")
 @Size(min = 2, max = 50, message = "Name length should be between 2 and 50")
 private String name;
 
 @NotNull(groups = BookNotNull.class, message="Book Author should not be null")
 private String author;
 
 @NotNull(groups = BookNotNull.class, message="Book Edition should not be null")
 private String edition;
 
 @NotNull(groups = BookNotNull.class, message="Release date should not be null")
 @Future(message = "Release date should not be past date")
 private Date releaseDate;

 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getAuthor() {
  return author;
 }
 public void setAuthor(String author) {
  this.author = author;
 }
 public String getEdition() {
  return edition;
 }
 public void setEdition(String edition) {
  this.edition = edition;
 }
 public Date getReleaseDate() {
  return releaseDate;
 }
 public void setReleaseDate(Date releaseDate) {
  this.releaseDate = releaseDate;
 }
 public interface BookNotNull {
 } 
}
In the above bean, @NotNull constraint is part of the BookNotNull validation group and @Size, @Future constraints belong to the Default group (which is specified by the JSR 303 API), as no special validation group is specified for them.

Now, we will test this using BookTest.java as shown below,
package com.bean.test;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;
import com.sample.bean.Book;
import com.sample.bean.Book.BookNotNull;

public class BookTest {
 
 private static Validator validator;

 public static void main(String args[]) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
        Calendar cal = Calendar.getInstance();
        Book b = new Book();
        b.setAuthor("Satish");
        b.setEdition("first");
        b.setName("j");
        b.setReleaseDate(new Date("07/26/2011"));
        b.setRating(1);
        Set<ConstraintViolation<Book>> constraintViolations = validator.validate(b, BookNotNull.class, Default.class);
        int count = constraintViolations.size();
        System.out.println("Total voilations: "+count);        
        Iterator it = constraintViolations.iterator();
        while(it.hasNext()){
         ConstraintViolation cv=(ConstraintViolation)it.next();
         System.out.println(cv.getMessage());
        }        
    }
}
Above, we have specified BookNotNull and Default groups in validate(). So, first only the constraints which are under BookNotNull group will be validated. If there is any violations, processing stops there(constraints under default group will not be validated). If no violations occur, then constraints under Default group will be validated.

If you specify only BookNotNull group in validate(), only constraints under BookNotNull group will be validated.
   

JSR 303 - Bean Validation with OpenJPA - Part II

0 comments
  
In the previous article, we have seen how to use built-in constraints defined by Bean Validation Specification. In this article, we will see how to implement our own custom constraints.

If the built-in constraints do not meet your requirements, you can create your own custom validators and constraints. There are two ways of doing this, Implementing from scratch or Combine constraints from already existing constraints(Compound Constraints).

Implementing from scratch:
To implement a new constraint from scratch you first need to know how JSR-303 constraints work.

A constraint is basically a pair of an annotation and its associated validator class. When a bean is validated, it is being scanned for all the constraint annotations. Once such annotation is found its associated validator is created and initialized with the annotation (the annotation in a way serves as the configuration for its validator). How does the framework know which validator to instantiate? well... the annotation indicates it, and it's best explained by an example.

In this example, we will create a 'User' bean and validate the user name, whether it is reserved name or not. First, create a @ReservedUser annotation as shown below,
package com.bean.validators;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = UserValidator.class)
@Documented
public @interface ReservedUser {

    String message() default "This UserName is reserved word."; 
    //String message() default "{username.reserved.message}";
    Class[] groups() default {};
    public abstract Class[] payload() default {};
} 
An annotation type is defined using the @interface keyword. All the defined attributes in above annotation are specified in the specification and mandatory for all constraint annotations. The specification of the Bean Validation API demands that all constraint annotations should define the below attributes:
  • message: This attribute can be used to set a custom error message that will be displayed if the constraint defined by the annotation is not met. If we want to set a message bundle key instead of a literal message, we should surround it with braces. So we can set message to either "This user name is reserved word." or "{username.reserved.message}". See the below NOTE for more information on this.
  • groups: This attribute can be used to associate a constraint with one or more validation processing groups. Validation processing groups can be used to influence the order in which constraints get validated, or to validate a bean only partially.
  • payload: This attribute can be used to attach extra meta information to a constraint. The Bean Validation standard does not define any standard metadata that can be used, but specific libraries can define their own metadata.
In addition, we annotate the annotation type with a couple of meta annotations:
  • @Target({ METHOD, FIELD, ANNOTATION_TYPE }): Says that methods, fields and annotation declarations may be annotated with @ReservedUser (but not type declarations).
  • @Retention(RUNTIME): Specifies that annotations of this type will be available at runtime by the means of reflection.
  • @Constraint(validatedBy = UserValidator.class): Specifies the validator to be used to validate elements annotated with @ReservedUser.
  • @Documented: Says that the use of @UpperCase will be contained in the JavaDoc of elements annotated with it.
NOTE: The specification define quite a powerful message interpolation mechanism for the error messages. The message can contain placeholders (surrounded by curly brackets) which can be replaced by the attributes defined in the annotation itself. Furthermore, the placeholders can also refer to keys defined in a resource bundle. In the later case, the placeholders will be replaced by their associated values in the bundle(see the commented line above). For example, as we did in the @ReservedUser annotation, it is considered a best practice to assign a default message value. This value actually consists of one parameter placeholder which refers to a key in a resource bundle ("username.reserved.message"). When the error message is resolved, the value of this key is looked up in the resource bundle and when found replaces the placeholder. By default, the validator will look for a resource bundle named ValidationMessages.properties in the classpath.
    Next, we need to implement a Constraint Validator, which is able to validate elements with the @ReservedUser annotation. To do so, we have to implement the interface ConstraintValidator as shown below,
    package com.bean.validators;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    public class UserValidator implements ConstraintValidator<ReservedUser, String> {
        public void initialize(ReservedUser constraintAnnotation) {
             //nothing to do
        }
        public boolean isValid(String username, ConstraintValidatorContext cvc) {
            if (username == null){
                return true;
            }else{
                if(username.equalsIgnoreCase("SATISH"))
                   return false;
                else
                   return true;
            }
        }
    }
    
    The ConstraintValidator interface specifies two type parameters, which we set in our implementation. The first specifies the annotation type to be validated by a ConstraintValidator (in our example ReservedUser), the second the type of elements, which the validator can handle (here String).

    The implementation of the validator is straightforward. The initialize() method gives us access to any attributes of the annotation (such as the min/max fields in case of the Size annotation), but as @ReservedUser doesn't define any such attributes, we have nothing to do here.

    What's interesting for us, is the isValid() method. It determines whether a given object is valid according to the @ReservedUser annotation or not.

    Next, create 'User.java' bean and define the custom constraint for username as shown below,
    package com.sample.bean;
    
    import com.bean.validators.ReservedUser;
    
    public class User {
     
     @ReservedUser(message = "Please use another username.")
     private String userName;
     private String userId;
     private int age;
     public String getUserName() {
      return userName;
     }
     public void setUserName(String userName) {
      this.userName = userName;
     }
     public String getUserId() {
      return userId;
     }
     public void setUserId(String userId) {
      this.userId = userId;
     }
     public int getAge() {
      return age;
     }
     public void setAge(int age) {
      this.age = age;
     }
    } 
    
    Now, create 'UserTest.java' program to test the validation as shown below,
    package com.bean.test;
    
    import static java.lang.System.out;
    import java.util.Calendar;
    import java.util.Iterator;
    import java.util.Set;
    import javax.validation.ConstraintViolation;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import javax.validation.ValidatorFactory;
    
    import com.sample.bean.User;
    
    public class UserTest {
     
     private static Validator validator;
    
     public static void main(String args[]) {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            validator = factory.getValidator();
            Calendar cal = Calendar.getInstance();
            User u = new User();
            u.setUserName("satish");
            Set<ConstraintViolation<User>> constraintViolations = validator.validate(u);
            int count = constraintViolations.size();
            out.println("Total voilations: "+count);        
            Iterator it = constraintViolations.iterator();
            while(it.hasNext()){
                ConstraintViolation cv=(ConstraintViolation)it.next();
                out.println(cv.getMessage());
            }        
        }
    } 
    
    Thats it, you're done. You can test it by changing the name in setUserName().

    Compound Constraints:
    Sometimes there is no real need to create constraint entirely from scratch. It is often the case where a constraint is either a specific variation of another constraint, or a combination of other constraints. The specification acknowledges that and makes it even easier to define such constraints.

    So, let's compose a new constraint annotation @ValidUserName, that comprises the constraints @NotNull, @Size and @ReservedUser as shown below,
    package com.bean.validators;
    
    import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import javax.validation.ReportAsSingleViolation;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    
    @NotNull
    @Size(min = 2, max = 14)
    @ReservedUser
    @Target( { METHOD, FIELD, ANNOTATION_TYPE })
    @Retention(RUNTIME)
    @Constraint(validatedBy = {})
    @Documented
    @ReportAsSingleViolation
    public @interface ValidUserName {
    
        String message() default "This Username is not Valid.";
        Class<?>[] groups() default {};
        public abstract Class<? extends Payload>[] payload() default {};
    } 
    
    As you can see, no validator is associated with this annotation. Instead, it is annotated with the @ReservedUser annotation which holds the reserved username validation. By default, when the validation is performed, all the constraints are evaluated (in our case, @NotNull, @Size, @ReservedUser constraints) and register any encountered violations. Sometimes you'd like only one error message to be reported. This is where the @ReportAsSingleViolation annotation becomes useful. This annotation indicates that on any constraint violation of any of the constraints, only one violation will be reported and all other reported violations will then be ignored.

    Now, we have created a compound constraint @ValidUserName. We can define only this constraint for validating username instead of @NotNull, @Size and @ReservedUser as shown below,
    package com.sample.bean;
    
    import com.bean.validators.ValidUserName;
    
    public class User {
     
     @ValidUserName
     private String userName;
    
            //Other fields
    } 
    
    In the next article, we will see about Validation Groups.
         

    JSR 303 - Bean Validation with OpenJPA - Part I

    0 comments
        
    JSR 303:
    JSR-303 is a specification for Bean Validation. It is an attempt to come up with a standard declarative validation framework. The infrastructure defined by JSR-303 enables you to describe the constraints using constraint annotations on your bean and validate your bean using constraint validators.

    OpenJPA:
    A new feature defined by the JPA 2.0 specification is the ability to integrate with JSR-303 bean validation provider. With minimal effort, OpenJPA 2.0 can be coupled with JSR-303 validation provider to provide runtime data validation. By combining these two technologies, you get a standardized persistence solution with the added ability to perform standardized java bean validation.

    What is Bean Validation?
    Most applications, especially those that gather input from a user, contain a significant amount of code to perform data validation. It is typically custom code, fragmented and littered throughout the application. Worse, there may be duplicate validation code at the presentation (Web) , business (EJB), and persistence layers. The task of keeping duplicate code in sync can be especially problematic. A slight modification in the code at one layer can lead to an unforeseen breakage in another.

    The Bean Validation API was designed to provide a standardized method for validating data within Java beans. As an added feature, it seamlessly integrates with several JEE6 technologies including JPA 2.0, JCA 1.6, and JSF 2.0. Additionally, JEE6 complaint servers are required to support bean validation and must include a validation provider. While a JEE6 environment provides some simplified packaging and configuration benefits, bean validation works equally well in a JSE environment.

    While the JSR-303 specification is very feature rich and extensible, there are three core concepts that will be of most interest to the majority of users: constraints, constraint violation handling, and the validator itself. Constraints are a fundamental component of bean validation. Constraints can be placed on Java beans and/or fields(attributes) to constrain the data within the bean. A constraint can either be defined using annotations or XML. The bean validation specification defines a small set of constraints(Built-in constraints) that must be included with every validation provider. This small set covers most types of simple validation in addition to a powerful regular expression based validator. If the built-in constraints don't fit the bill, you can very easily build your own custom validators and constraints. Let's start by looking at some simple constraints and then move to creating some custom constraints.

    Pre-requisites:
    Before going to the examples, download the required jar file from here. At the time of writing this article, the latest version is 2.1.0. Download the apache-openjpa-2.1.0.zip file, extract it, and copy the openjpa-all-2.1.0.jar file and include it in your classpath.

    How to use Built-in Constraints:
    In the following example, I am going to explain how to use Built-in Constrains defined by the bean validation specification.

    Create a java bean class Book.java and define some simple built-in constraints as shown below,
    package com.sample.bean;
    
    import java.util.Date;
    import javax.validation.constraints.Future;
    import javax.validation.constraints.Max;
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Pattern;
    import javax.validation.constraints.Size;
    
    public class Book {
    
     @NotNull(message="Book Name should not be null")
     @Size(min = 2, max = 50, message = "Name length should be between 2 and 50")
     private String name;
     
     @NotNull(message="Book Author should not be null")
     private String author;
     
     @NotNull(message="Book Edition should not be null")
     private String edition;
     
     @NotNull(message="Release date should not be null")
     @Future(message = "Release date should not be past date")
     private Date releaseDate;
    
     @Min(1)
     @Max(5)
     private int rating;
     
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public String getAuthor() {
      return author;
     }
     public void setAuthor(String author) {
      this.author = author;
     }
     public String getEdition() {
      return edition;
     }
     public void setEdition(String edition) {
      this.edition = edition;
     }
     public Date getReleaseDate() {
      return releaseDate;
     }
     public void setReleaseDate(Date releaseDate) {
      this.releaseDate = releaseDate;
     }
     public int getRating() {
      return rating;
     }
     public void setRating(int rating) {
      this.rating = rating;
     } 
    }
    
    NOTE: It is possible to put the annotations on the fields or on the setter methods of the bean properties. Personally, I like putting them on the fields as it's easier to pick up when reading the code.
     
    Built-In Bean Validation Constraints:

    Constraint Description Example
    @AssertFalse The value of the field or property must be false.
    @AssertFalse
    boolean isUnsupported;
    @AssertTrue The value of the field or property must be true.
    @AssertTrue
    boolean isActive;
    @DecimalMax The value of the field or property must be a decimal value lower than or equal to the number in the value element.
    @DecimalMax("30.00")
    BigDecimal discount;
    @DecimalMin The value of the field or property must be a decimal value greater than or equal to the number in the value element.
    @DecimalMin("5.00")
    BigDecimal discount;
    @Digits The value of the field or property must be a number within a specified range. The integer element specifies the maximum integral digits for the number, and the fraction element specifies the maximum fractional digits for the number.
    @Digits(integer=6, fraction=2)
    BigDecimal price;
    @Future The value of the field or property must be a date in the future.
    @Future
    Date eventDate;
    @Max The value of the field or property must be an integer value lower than or equal to the number in the value element.
    @Max(10)
    int quantity;
    @Min The value of the field or property must be an integer value greater than or equal to the number in the value element.
    @Min(5)
    int quantity;
    @NotNull The value of the field or property must not be null.
    @NotNull
    String username;
    @Null The value of the field or property must be null.
    @Null
    String unusedString;
    @Past The value of the field or property must be a date in the past.
    @Past
    Date birthday;
    @Pattern The value of the field or property must match the regular expression defined in the regexp element.
    @Pattern(regexp="\\(\\d{3}\\)\\d{3}-\\d{4}")
    String phoneNumber;
    @Size The size of the field or property is evaluated and must match the specified boundaries. If the field or property is a String, the size of the string is evaluated. If the field or property is a Collection, the size of the Collection is evaluated. If the field or property is a Map, the size of the Map is evaluated. If the field or property is an array, the size of the array is evaluated. Use one of the optional max or min elements to specify the boundaries.
    @Size(min=2, max=240)
    String briefMessage;


    Create a java class BookTest.java to test the constraints defined in java bean as shown below,
    package com.bean.test;
    
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Iterator;
    import java.util.Set;
    import javax.validation.ConstraintViolation;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import javax.validation.ValidatorFactory;
    import com.sample.bean.Book;
    
    public class BookTest {
     
     private static Validator validator;
    
     public static void main(String args[]) {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            validator = factory.getValidator();
            Calendar cal = Calendar.getInstance();
            Book book = new Book();
            //book.setAuthor("Satish");
            //book.setEdition("first");
            //book.setName("java");
            //book.setReleaseDate(new Date("07/21/2011"));
            book.setRating(1);
            Set<ConstraintViolation<Book>> constraintViolations=validator.validate(book);
            int count = constraintViolations.size();
            System.out.println("Total voilations: "+count);        
            Iterator it = constraintViolations.iterator();
            while(it.hasNext()){
               ConstraintViolation cv=(ConstraintViolation)it.next();
               System.out.println(cv.getMessage());
            }        
        }
    }
    On line 19, we get a Validator object from the ValidatorFactory, we use this validator to validate the 'book' object. The validate() method returns a set of ConstraintViolation objects, which we can iterate through in order to see which validation errors occured.

    In the next article, we will see how to create our own custom constraints.
           

    Submit Website/Blog to Search Engines

    on March 01, 2011 0 comments
       
    Search Engine Optimization (SEO) aims at increasing the volume and improving the quality of traffic to a website from search engine results. Search engines work on different algorithms to analyze the contents and keywords, and present the search results. Google, for instance, assigns page ranks to the sites and sites that rank highly will appear early in the results. Of course, many other factors are considered by search engines, such as relevance, unique content, coding and quality of links. The major search engines know that revealing these factors will only encourage manipulation of the ranking system and have thus been secretive about how the ranking algorithms work.

    While no SEO consultant can be absolutely certain about how each search engine views your site, the common agreement is that the more visible your site is on the internet, the higher your ranking will eventually be. Having your site linked to by many other sites and indexed by different search engines increase its exposure and visibility. In this article, I provided a list of search engines where you can submit your website or Blog URLs for free and have your site or Blog indexed by the search engines.

    Website Indexing:

    Unless you have created a private blog, it is a matter of time that your blog is indexed by the major search engines like Google, Yahoo and MSN. One of the fastest ways to have your site indexed is to get another site that is already in the search engine listings to link to you. When the search engine crawlers visit that site, they will find your site and index it

    Before we proceed to the list of search engine sites, there are a few points to note:

    1. To check if your site has been indexed by a search engine, enter the full URL into their search query. For some search engines like Microsoft Live Search, enter site: followed by the full URL. If you see your site appearing in the search results, it has been indexed and there is no need to resubmit the site.

    2. If your Blog has been linked to by Blog Directories, websites or Blogs, you may see these other sites that mention your Blog appearing first in the search results. More likely than not, they have a higher page rank. Scroll through the remaining search result pages and you will probably find a listing that is solely about your Blog.

    3. When submitting your site, you do not need to submit the URL of each individual webpage. Submit only the top-level webpage and for Blogger Blogs, it will be an address like this http://blogname.blogspot.com without the www. before the blogname.

    4. You can submit your sitemap to Google and login to Google Webmaster Tools site to know the status of the indexing and view traffic statistics. Also, submit your sitemap to Yahoo! to find out more about the index and links to your site.

    5. If you add your URL in Yahoo!, it will appear in their other search sites like AlltheWeb and AltaVista as well. Similarly, AOL Search uses the data by Google.

    6. Some of the sites send advertisements and newsletters to you in exchange for free submission. If you don't want that, remember to opt out of it. Avoid having your regular email account filled with these mail by creating another free web-based email account just for website submissions.

    7. Since search engines have different standards of content, design and technical specifications, submission of your site does not guarantee that it will be included in their database.

    List of Search Engines:
    You may submit your site URL to these search engines for Free. If you lack the time, submit your site to the top few leading search engines.
    Website Submission Services:
    There are many sites on the internet offering free website submission services to search engines. The list of search engines are by and large the same. For a fee, some of them offer to send your URL to more than a hundred search engines. Is it necessary to have your webpage listed in all the smaller search engines? We think that Google, Yahoo! and MSN have cornered such a large share of the market that it is sufficient just to have your website listed there. However, the decision is yours to make. For a start, you may want to use their free services and monitor the traffic.
    I shall update this list every now and then, so bookmark this page and revisit this page for new updates.
     

    Google May Be Crawling AJAX Now – How To Best Take Advantage Of It

    on February 01, 2011 1 comments

    In October 2009, Google proposed a new standard for implementing AJAX on web sites that would help search engines extract the content. Now, there’s evidence this proposal is either live or is about to be. Read on for more details on the proposal, how it works, and why it might be past the proposal stage.

    The Trouble With AJAX
    Historically, search engines have had trouble accessing AJAX-based content and this proposal would enable Google (and presumably other search engines that adopted the standard) to index more of the web. The standard SEO advice for AJAX implementations has traditionally been to follow accessibility best practices. If you build the site with progressive enhancement or graceful degradation techniques so that screen readers can render the content, chances are that search engines can access the content as well. Last May, I outlined some of the crawlability issues with AJAX and options for search-friendly implementations.
    Google has offered advice on AJAX as well, including:
    One of the primary search engine problems with AJAX is that it generates URLs that contain a hash mark (#). Since hash marks are also used for named anchors within a page, search engines typically ignore everything in a URL beginning with one (called the URL fragment). So, for instance, Google would see the following two URLs as identical:
    • http://www.buffy.com/seasons.php
    • http://www.buffy.com/seasons.php#best=2
    Google’s AJAX Proposal
    With Google’s proposal, an AJAX-generated URL that contains a hash mark (#) would also be replaced with a URL that uses #! in place of #. So, the second URL above would become http://www.buffy.com.seasons.php#!best=2. When Googlebot encounters the exclamation point after the hash mark, it would then request the URL from the server using a syntax that would replace the #! with ?_escaped_fragment_=.
    Still with me? All this means is that when Googlebot encounters:
    http://www.buffy.com/seasons.php#!best=2
    it will request the following URL from the server:
    http://www.buffy.com/seasons.php?_escaped_fragment_=best=2
    Why, you ask? Well because ?_escaped_fragment_= in the URL tells the server to route the URL request to the headless browser to execute the AJAX code and render a static page.But, you might protest, I don’t want my URLs in the search results to look like that! Not to worry,  Google requests the URL using that syntax, but then translates the ?_escaped_fragment_= back into #! when displaying it to searchers.

    How Do I Implement This?
    This implementation basically requires that you:
    • Modify your AJAX implementation so that URLs that contain hash marks (#) are also available via the hash mark/exclamation point (#!) combination (or, as I recommend below, that you replace the # versions entirely with the #! ones).
    • Configure a headless browser on your web server that processes the ?_escaped_fragment_= versions of the URLs, executes the JavaScript on the page and returns a static page.
    Oh, you still have questions? I have answers! Well, and some questions of my own.

    What about all those links?
    Is Google going to consolidate all links to the # version of the URL and attribute them to the #! version? It appears that the answer is no. urrently, all links to URLs that contain a hash mark are attributed to the URL before the fragment, and that will continue to be the case.  And the canonical tag won’t work in this case, since Google doesn’t process the # version of the URL. So returning to our earlier example, all links to http://www.buffy.com/seasons.php#best=2 are attributed to http://www.buffy.com/seasons.php.

    Wait, do we need to start using #! instead of #?
    You likely don’t want to implement this in such a way that the # and #! URLs co-exist. Instead, you’ll want to replace # URLs with #! URLs. You can’t redirect search engine bots, of course (same reason bots can’t crawl and index the AJAX URLs as is).  This means that as noted above, the pages won’t get credit for past links to the # version of the URLs. You should ensure that the #! version of the URLs is what displays in a visitor’s browser though, so that any new links are to the (now indexable) #! versions. What about visitors coming from existing links to the # versions of the URLs? You’ll want to add code that transforms the # version of the URLs to the #! version (see below for more on that).

    How do I create #! URLs in place of # URLs?
    That’s pretty straightforward. Just (I know, there is not “just”) modify the AJAX code that creates URLs to output #! URLs instead of # URLs. As noted above, for any existing AJAX pages that use #, you’ll want to redirect visitors to the new URLs that use #!. This won’t cause Google to transfer links from the # versions to the #! versions but it will ensure that visitors will see only the #! version and therefore, any new links will be to that version, which will causes Google to start accruing PageRank for those pages. Obviously, you’ll want to get any new links to the versions of the pages that Google will index so those pages have a better chance at ranking well.

    Below are the few suggestions for redirecting visitors from the # versions to the #! versions of the URLs.
    • JavaScript – You can use document.location, such as: <script type=”text/javascript”> document.location=”http://www.buffy.com/seasons.php#!best=2″; </script>
    • PHP – You can write a short PHP script, such as: <?php header(“HTTP/1.1 301 Moved Permanently”); header(“Location: http://www.buffy.com/seasons.php#!best=2″); ?>
    • .htaccess – For Apache servers, you can use the NE flag in a rewrite rule, as shown below (although this really only works if you’re moving to the #! structure from a non-# URL):RewriteCond %{QUERY_STRING} ^best=(.*)$ RewriteRule ^seasons.php$ /seasons.php#!%1? [R=301,NE]
    • Meta refresh – generally, a meta refresh isn’t recommended for redirects as search engines do a better job of following 301s, but in this case, you’re only redirecting visitors. You can add code similar to the following to the <Head> section of the original page: <meta http-equiv=refresh content=”0; http://www.buffy.com/seasons.php#!best=2″>
    Please click here to get more information on this.
     

    How to publish code snippets in Blog

    on January 21, 2011 0 comments
        
    For those who like to post code snippets on your blogs, Syntax Highlighter 3.083 is a very useful tool. If you are using blogspot, you often have a mess with your code. Syntax Highlighter is a solution for you. I googled a bit and found couple of articles which I found useful. To know how to use Syntax Highlighter, please follow the following steps:

    Login to your Blogger Account and Click on Design link and Click on Edit HTML, which is highlighted in the image shown below,


    Now follow these simple 3 steps to publish code snippets in blogger:

    1. Search for “/head” tag in the HTML template and paste the below script tags above that. 
    [Note]: Check “Expand Widget Templates” if search result is not found.
    <script src="http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js" type="text/javascript">
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJava.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCSharp.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCss.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushSql.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushVb.js' type='text/javascript'/>
    <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushXml.js' type='text/javascript'/> 
    2. Search for “/body” and Paste the below javascript code above “/body”
    <script language="javascript">
    dp.SyntaxHighlighter.BloggerMode();
    dp.SyntaxHighlighter.HighlightAll('code');
    </script> 
    3. Paste the below CSS code before “]]>” in your HTML Template
    .dp-highlighter
    {
     font-family: "Consolas", "Monaco", "Courier New", Courier, monospace;
     font-size: 12px;
     background-color: #E7E5DC;
     width: 99%;
     overflow: auto;
     margin: 18px 0 18px 0 !important;
     padding-top: 1px; /* adds a little border on top when controls are hidden */
    }
    
    /* clear styles */
    .dp-highlighter ol,
    .dp-highlighter ol li,
    .dp-highlighter ol li span
    {
     margin: 0;
     padding: 0;
     border: none;
    }
    
    .dp-highlighter a,
    .dp-highlighter a:hover
    {
     background: none;
     border: none;
     padding: 0;
     margin: 0;
    }
    
    .dp-highlighter .bar
    {
     padding-left: 45px;
    }
    
    .dp-highlighter.collapsed .bar,
    .dp-highlighter.nogutter .bar
    {
     padding-left: 0px;
    }
    
    .dp-highlighter ol
    {
     list-style: decimal; /* for ie */
     background-color: #fff;
     margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */
     padding: 0px;
     color: #5C5C5C;
    }
    
    .dp-highlighter.nogutter ol,
    .dp-highlighter.nogutter ol li
    {
     list-style: none !important;
     margin-left: 0px !important;
    }
    
    .dp-highlighter ol li,
    .dp-highlighter .columns div
    {
     list-style: decimal-leading-zero; /* better look for others, override cascade from OL */
     list-style-position: outside !important;
     border-left: 3px solid #6CE26C;
     background-color: #F8F8F8;
     color: #5C5C5C;
     padding: 0 3px 0 10px !important;
     margin: 0 !important;
     line-height: 14px;
    }
    
    .dp-highlighter.nogutter ol li,
    .dp-highlighter.nogutter .columns div
    {
     border: 0;
    }
    
    .dp-highlighter .columns
    {
     background-color: #F8F8F8;
     color: gray;
     overflow: hidden;
     width: 100%;
    }
    
    .dp-highlighter .columns div
    {
     padding-bottom: 5px;
    }
    
    .dp-highlighter ol li.alt
    {
     background-color: #FFF;
     color: inherit;
    }
    
    .dp-highlighter ol li span
    {
     color: black;
     background-color: inherit;
    }
    
    /* Adjust some properties when collapsed */
    
    .dp-highlighter.collapsed ol
    {
     margin: 0px;
    }
    
    .dp-highlighter.collapsed ol li
    {
     display: none;
    }
    
    /* Additional modifications when in print-view */
    
    .dp-highlighter.printing
    {
     border: none;
    }
    
    .dp-highlighter.printing .tools
    {
     display: none !important;
    }
    
    .dp-highlighter.printing li
    {
     display: list-item !important;
    }
    
    /* Styles for the tools */
    
    .dp-highlighter .tools
    {
     padding: 3px 8px 3px 10px;
     font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
     color: silver;
     background-color: #f8f8f8;
     padding-bottom: 10px;
     border-left: 3px solid #6CE26C;
    }
    
    .dp-highlighter.nogutter .tools
    {
     border-left: 0;
    }
    
    .dp-highlighter.collapsed .tools
    {
     border-bottom: 0;
    }
    
    .dp-highlighter .tools a
    {
     font-size: 9px;
     color: #a0a0a0;
     background-color: inherit;
     text-decoration: none;
     margin-right: 10px;
    }
    
    .dp-highlighter .tools a:hover
    {
     color: red;
     background-color: inherit;
     text-decoration: underline;
    }
    
    /* About dialog styles */
    
    .dp-about { background-color: #fff; color: #333; margin: 0px; padding: 0px; }
    .dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; }
    .dp-about td { padding: 10px; vertical-align: top; }
    .dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; }
    .dp-about .title { color: red; background-color: inherit; font-weight: bold; }
    .dp-about .para { margin: 0 0 4px 0; }
    .dp-about .footer { background-color: #ECEADB; color: #333; border-top: 1px solid #fff; text-align: right; }
    .dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; color: #333; width: 60px; height: 22px; }
    
    /* Language specific styles */
    
    .dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; }
    .dp-highlighter .string { color: blue; background-color: inherit; }
    .dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; }
    .dp-highlighter .preprocessor { color: gray; background-color: inherit; } 

    Done! Those were the changes to be made in the HTML Template and now you can start posting your source code in blogger as shown below:
    While writing a post, select “Edit HTML” to write the blog post in HTML mode and wrap your source code snippet with a pre tag and add name=”code” and class=”“, after wrapping your source code it should look like something below,
    <pre name="code" class="csharp">
    //your source code goes here
    </pre>
    

    Here is the list of supported languages,

    Language Aliases
    C++ cppcc++
    C# c#c-sharpcsharp
    CSS css
    Delphi delphipascal
    Java java
    Java Script jsjscriptjavascript
    PHP php
    Python pypython
    Ruby rbrubyrailsror
    Sql sql
    VB vbvb.net
    XML/HTML xmlhtmlxhtmlxslt
      

    How to Add the Facebook Like Button Below every Post

    on January 11, 2011 0 comments
      
    Facebook has come up with  a new set of Social plugins which enable you to provide engaging social experiences to your users with just a line of HTML. The Facebook Like Button is One of them. The Facebook like button will allow your readers to quickly share your posts with their Facebook Friends. You can also get to know how many people liked your Blog Post . 

    1. Go to this link and select the options and click on Get Code button (Code will be updated with these details).
     
    2. Facebook provides code in two ways: IFrame and XFBML. You can select any one of them, XFBML has some advanced options than IFrame.

    3. Copy the code(either IFrame or XFBML). Log in to your Blogger Account and go to Design > Edit HTML and click on the check box which says “Expand Widget Templates”.

    4. Look for <data:post.body/> and immediately below that, paste the copied code. 


    5. If you choose XFBML, then look for </head>
    and immediately above that paste the following code,

        <script src='http://connect.facebook.net/en_US/all.js#xfbml=1' type='text/javascript'/>

       (Note: You don't have to add this if you have already added this code for some other Facebook widget)

    6.  Save the template and you should see the Like Button on each of your posts.

          

    How to Hide Your Post Date, Time and/or Author

    on January 01, 2011 0 comments

    Some blog authors may want to hide Post date, time and author name. May be they want to see their blog looks clear or everything. Now, I will show you the trick to "hide your post date, time and or author". The methods is very simple, just find the code that I pointed to you and delete it. You can chose which part want to delete, date only, time only, author only or it all. Before doing any changes make sure you have the backup copy of the code.

    1. Login to blogger and go to "Layout --> Edit HTML"
    2. Click on the "Download Full Template" to back up your template first.
    3. Check on the "Expand Widget Templates" check box.



    For Hiding Post Date:
    Find this code and delete it.
    <data:post.dateHeader/>


    For Hiding Post Time:
    Find this code and delete it.


    For Hiding Post Author:
    Find this code and delete it.
    <span class='post-author vcard'>
    <b:if cond='data:top.showAuthor'>
    <data:top.authorLabel/>
    <span class='fn'><data:post.author/></span>
    </b:if>
    </span>

     
    Now, save your editing and check you changes.