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.

12 comments:

  1. How does applyCustomConfiguration() get called? I am trying to do something similar but not for a mobile site and this method is not being called by the container. I was expecting it to be called automatically.

    I have posted a question here if you would like more detail - https://groups.google.com/forum/?fromgroups#!topic/sitemesh2-users/2t7vj2Hlexg

    ReplyDelete
    Replies
    1. SpringMobileSiteMeshFilter class and ConfigurableSiteMeshFilte class are implementations of a Filter interface. This applyCustomConfiguration method is called through the init method in the filter which is invoked by your web container.

      Delete
  2. Hi - I have configured SiteMesh 3 and as the steps mentioned by I have configured SpringMobile(downloaded spring-mobile-device-1.0.0.M3.jar). But I am facing some challenges. Please help.

    1) In the below line it is expecting SiteMeshContext instead of WebAppContext. I have modified it. Is that fine ?

    public String[] selectDecoratorPaths(Content content, WebAppContext context)
    2) How I have to configure mvc interceptor in the dispatcher?

    Thanks in advance.

    ReplyDelete
    Replies
    1. Hi,
      I have used following sitemesh dependancy.

      org.sitemesh
      sitemesh
      3.0-alpha-2


      It only allows WebAppContext. And could you please share your dependency.

      Delete
  3. Hi - I m new in spring, I have setup the mvc interceptor like this.
    1) mvc-dispatcher-servlet.xml code










    2)
    mvc-dispatcher
    org.springframework.web.servlet.DispatcherServlet
    1



    mvc-dispatcher
    *.htm


    contextConfigLocation
    /WEB-INF/mvc-dispatcher-servlet.xml



    org.springframework.web.context.ContextLoaderListener


    3) When I am trying to deploy it through weblogic , I am getting exception - org.xml.sax.SAXParseException which lacks a String contructor, original message - Document root element "interceptors", must match DOCTYPE root "null"

    Can anyone of you please help ASAP? Thanks in advance.

    ReplyDelete
    Replies
    1. I think either your web.xml or servlet xml cannot be parse by the parser. Have a good look to check the errors in those files. It would be better if you can share your code here and send the link.
      http://pastebin.com/

      Delete
  4. Thanks Eshan for your reply, I have shared the code in pastebin.com. Please have a look and let me know ASAP. I am using weblogic as a server.Please let me know if you need more info or when u will be available on net.

    ReplyDelete
    Replies
    1. Send me that link where you paste the code in pastebin :-)

      Delete
    2. Hi Eshan - Please let me know ASAP, if you got the issues, present in my code. I have already provide u the link - http://pastebin.com/x4KH8Jts

      Delete
  5. sorry the link is - http://pastebin.com/x4KH8Jts

    ReplyDelete
    Replies
    1. Hi Eshan - Please let me know ASAP, if you got the issues, present in my code. I have already provide u the link - http://pastebin.com/x4KH8Jts

      Delete
  6. Hi Eshan - Could you help me with some code to extract content of a particular Div , using sitemesh 3 . I have tried a lot but filed. For your reference below code I have put in sitemesh3.xml






    ReplyDelete