Creating a mobile version of your website with Spring Mobile and Sitemesh

by Roberto van der LindenMay 3, 2012

About a year ago I developed an Android app for my website, but as not everybody has an Android device I wanted to create a mobile version of my website. In the mobile version I want to present slightly different data to make it look more like the app. In this post I will show you how I have used Spring mobile to determine which version of the site the user wants to visit and how I used Sitemesh to select the correct decorator.

Spring mobile

Spring mobile provides you some nice features to either detect mobile devices or to give the user a choose between the “mobile” or “normal” site. In my case I want redirect the user to the mobile website based on the device and make the site available on a different URL (http://m.yourcoolsite.com).

If you happen to use maven (like me) you need to add the Spring Milestone Repository and the dependency:

    <repository>
        <id>org.springframework.maven.milestone</id>
        <name>Spring Maven Milestone Repository</name>
        <url>http://maven.springframework.org/milestone</url>
    </repository>

    <dependency>
        <groupId>org.springframework.mobile</groupId>
        <artifactId>spring-mobile-device</artifactId>
        <version>1.0.0.RC1</version>
    </dependency>

The configuration for resolving the device and switching the site is pretty simple. I configured two interceptors and the SiteSwitcherHandlerInterceptor allows you to configure the “mDot” factory method to redirect your users to the mobile url.

<mvc:interceptors>
    <!-- On pre-handle, resolve the device that originated the web request -->
    <beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
    <!-- On pre-handle, redirects mobile users to "m.yourcoolsite.com" (declare after DeviceResolverHandlerInterceptor) -->
    <beans:bean class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor" factory-method="mDot">
        <beans:constructor-arg value="yourcoolsite.com" />
    </beans:bean>
</mvc:interceptors>

That is all there is for the Spring configuration, so next up is the Sitemesh configuration.

Sitemesh

In my normal website I use Sitemesh (version 2.3) as my layout templating framework.  Now with the mobile version I want a complete different layout (no header or navigation). Of course you can have this all done by great CSS, but I also want sometimes to display different information. So I want to use a different decorator for the mobile website.  The first page of my website is a login screen.  On this page I want to have a link to the normal website, so that the user can decide which site he wants to use, even after I redirected the user to a mobile site.  Here is a screenshot of my mobile login page:

login

The first thing we need to do is to configure an extra decorator for the mobile website. So in my decorators.xml I have added the following decorator with the name mobile:

    <decorator name="main" page="main.jsp">
        <pattern>**</pattern>
    </decorator>

    <decorator name="mobile" page="mobile-main.jsp"/>

Here you can see that I have created a separate .jsp file for the mobile website. The next thing we need to do is to let Sitemesh decide which decorator it needs to use when a mobile user is visiting the site. In sitemesh.xml I configured the decorator-mapper with my custom created mapper:

<property name="decorators-file" value="/WEB-INF/decorators.xml"/>

<decorator-mappers>
    <mapper class="nl.orange11.web.SpringMobileParameterDecoratorMapper">
        <param name="config" value="${decorators-file}"/>
    </mapper>
</decorator-mappers>

SpringMobileParameterDecoratorMapper.java:

public class SpringMobileParameterDecoratorMapper extends ConfigDecoratorMapper {
    private String decoratorName = null;

    public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException {
        super.init(config, properties, parent);
        decoratorName = properties.getProperty("decorator.name", "mobile");
    }

    public Decorator getDecorator(final HttpServletRequest request, final Page page) {
        SitePreference sitePreference = SitePreferenceUtils.getCurrentSitePreference(request);

        if(sitePreference != null && sitePreference.isMobile()){
            return getNamedDecorator(request, decoratorName);
        }

        return super.getDecorator(request, page);
    }
}

In the mapper I check if the user has specified a site preference. The util method that I use checks if the URL parameter that specifies a site preference is present. If this is not the case, then the util method will use your device type as a preference. Based on the outcome I decide which decorator I want to use.

Controller

Because I have different jsp files for the mobile site, but still using the same controller I need to change the view that is passed into the ModelAndView object based on the site preferences.

SitePreference sitePreference = SitePreferenceUtils.getCurrentSitePreference(request);
    if (sitePreference == SitePreference.MOBILE) {
        view = "mobile/" + view;
    }

As you can see it does not require a lot of code to configure your mobile website. You will spend most of the time designing a good mobile layout. I have used JQueryMobile, as I think it is a great framework that allows you to quickly create a good looking interface for your mobile website. It is also cross-platform, so you don’t need to create different views for smartphone, tablet or desktop platforms.

Well that’s it! I hope that my post helped some of you in your journey of creating great mobile websites 🙂