Monday, April 30, 2012

Spring Mobile and Sitemesh Integration

In modern technology era mobile based technology plays a major role. Trend has increased to use mobile phones for internet access.So there is new software requirement to add mobile support for existing web sites.

In this post I am going to explain an easy way of doing this using spring mobile and sitemesh. Requirement : Identify the device which the request comes from and apply the decorators according to the device.(css files and other specific images) The easiest way to do is use a filter in web.xml and detect the device. So in this post I use a filter in web.xml as follows.
  
 
      sitemesh
      com.mycompany.sitemesh.SpringMobileSiteMeshFilter
     
  
       sitemesh
       *.do
  

Once the url pattern maps it will trigger above site mesh filter. SpringMobileSitemeshFilter is an sub class of ConfigurableSitemeshfilter (API) Which comes with sitemesh pacage. In this specific implementation I have override applyCustomConfiguration method where we can apply specific decorators programatically.


package com.mycompany.sitemesh;

import org.sitemesh.builder.SiteMeshFilterBuilder;
import org.sitemesh.config.ConfigurableSiteMeshFilter;

public class SpringMobileSiteMeshFilter extends ConfigurableSiteMeshFilter {

    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
      System.out.println("In SpringMobileSiteMeshFilter");
      builder.setCustomDecoratorSelector(
        new SpringMobileDecoratorSelector(builder.getDecoratorSelector()));
    }
}

You can see that I have used SpringMobileDecoratorSelector which uses spring mobile functionality to identify the device and apply the decorator.


import java.io.IOException;

import org.sitemesh.DecoratorSelector;
import org.sitemesh.content.Content;
import org.sitemesh.webapp.WebAppContext;
import org.springframework.mobile.device.site.SitePreference;

public class SpringMobileDecoratorSelector implements
        DecoratorSelector {
    private final DecoratorSelector fallbackSelector;

    public SpringMobileDecoratorSelector(
            DecoratorSelector fallbackSelector) {
        this.fallbackSelector = fallbackSelector;
    }
    
    public String[] selectDecoratorPaths(Content content, WebAppContext context) {

        final SitePreference sitePreference = (SitePreference) context.getRequest().getAttribute("currentSitePreference");

        System.out.println("In SpringMobileDecoratorSelector");
        
        final String decorator;

        if (sitePreference.isMobile()) {
         System.out.println("Mobile");
            decorator = "/WEB-INF/decorators/mobile.jsp";
        } else {
         decorator = "/WEB-INF/decorators/default.jsp";
         System.out.println("PC");
        }

        if (decorator != null) {
            return decorator.split(",");
        } else {
            // Otherwise, fallback to the standard configuration.
            try {
                return fallbackSelector.selectDecoratorPaths(content, context);
            } catch (IOException e) {
                throw new IllegalStateException(e);
            }
        }
    }   
    
}
You might be wonder how this works. And where this request parameter called currentSitePreference is being set. Actually it is not a magic. I use spring mvc interceptor to set that request parameter.
 We can configure it in our dispatcher servlet in following manner.


  
 
       
             
  
Above two beans a responsible of detecting the device and set that parameter. And then we can simply apply the jsp files by checking the isMobile attribute. Final outcome is when the request comes form a mobile device it applies mobile jsp and do the decorating part. If it comes form a normal pc then it applies default. jsp and and do the pc related decorating.