Tuesday, January 4, 2011

Spring Mobile, jQuery Mobile and SiteMesh

I just realized that I haven't published a blog entry in a while. Time just flies by. Anyway, I am in the midst with several other volunteers to prepare for the Atlanta-based DevNexus developer conference which will take place March 21-22.

For this year's conference I reworked the conference website application using Spring (MVC) 3.0, JPA 2.0 etc. In addition to standard clients, I started looking into supporting mobile clients as well.

My requirement was to provide a decent looking mobile interface in a reasonable amount of time (heck, it is all done during my spare-time afterall). Plus, I wanted to support multiple mobile devices at once. Out of that reason I ruled out a native client implementation (at least for now).

Another option, would have been to look at other development frameworks such as PhoneGap and Appcelerator, something I may still have to do down the road.

As I have been using jQuery quite a bit, I started exploring it using either jQTouch or jQuery Mobile. I opted into looking at jQuery Mobile as it is the official jQuery sanctioned project.

As it turns out, you can easily create create some nice looking UIs using jQuery Mobile. As an example, just point, your mobile browser, e.g. Android to http://www.devnexus.com/. This is pretty impressive considering that I have been using an Alpha 2 version with just standard theming and functionality.

I still have to work on the detail pages, but the main landing page looks fairly nice out of the box using minimal amounts of code.

On the server-side, I am using Spring Mobile, which currently is available as a M2 release. What Spring Mobile allows you to do is to detect from within your Spring MVC controllers, whether the incoming request originates from a mobile device or not.

If you need to detect specific device capabilities, you can even use a WurflDeviceResolver, but for my use case I simply need to know whether a mobile device request is coming in or not. If so, forward to a mobile version of the respective controller's jsp page.

One, question I had to solve was how to make everything work with SiteMesh, which I use for templating purposes. As I use the same Urls for mobile and standard clients (No site-switching), I ended up needing to create a custom SiteMesh DecoratorMapper extending AbstractDecoratorMapper.



public class SpringMobileParameterDecoratorMapper extends AbstractDecoratorMapper {
    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) {

        final Device device = DeviceResolverHandlerInterceptor.getCurrentDevice(request);

        if (device != null && device.isMobile()) {
         return getNamedDecorator(request, decoratorName);
        } else {
         return super.getDecorator(request, page);
        }

    }
} 

It may not be the bestapproach to have a hard dependency onto Spring Mobile in my SiteMesh DecoratorMapper...but it works nicely so far.

12 comments:

Keith Donald said...

Awesome! I think it makes sense for Spring Mobile to set a boolean "mobileSite" request attribute you could use in your decorator. This would keep your decorator decoupled from Spring Mobile APIs. Also, the "mobileSite" value could be set based on the resolved SitePreference, which considers the user's preference in addition to their Device user agent.

Thanks for taking the time to share what you're working on!

Keith

Gunnar Hillert said...

Keith, thanks for the comment. That makes sense. But ultimately, you still have to create a custom DecoratorMapper. The provided one that is closed in functionality "ParameterDecoratorMapper" expects the name of the to-be-used decorator as the request parameter's value - Maybe not what you want either.

Anyway, creating your own DecoratorMapper is not hard - But can maybe the Spring Mobile documentation include a few pointers regarding dealing with the most common Java templating frameworks: Tiles and SiteMesh? I think that might be helpful to folks.

Marcin Muras said...

Could you add similar example but with Tiles? :) Thanks

suntrack said...

I did apply jQuery Mobile for my New Year vacation. This is a great project. But, the only concern I have is at the moment this product in Alpha release and I am not sure it is production ready.

Thanks
//
Reza

Gunnar Hillert said...

@Marcin: Take a look at the following blog post: http://blog.springsource.com/2010/11/19/spring-into-mobile-application-development/ There, Keith provides a pointer on how you can use Spring Mobile with Tiles. I am not a Tiles fan...have been using SiteMesh for most of my projects ;-)

Gunnar Hillert said...

@suntrack: I know, the alpha-version tag certainly is a bit scary - But then again I am just providing a non-critical value-add to a non-profit conference website.

Thus, if you need to provide an enterprise mission-critical mobile-web-app, you may want to take another look at the other options (jQTouch being an option for instance)

That being said - It looks like jQuery Mobile has some serious backers incl. Blackberry, Palm, Nokia etc. Plus they mention n their website (http://jquerymobile.com/2010/11/jquery-mobile-alpha-2-released/) to have a 1.0 release out in early 2011. Mobile is a fast moving, dynamic space...lots of frameworks to choose from.

S.G. said...

Gunnar,

i am actually a fellow AJUG'er so i was happy to see this post by a local guy... anyway i am having some issues with my spring/sitemesh based app and jQM. right now the main thing i am trying to figure out is why when my response has 2 pages in it, like the jQM docs show that is possible, the additional pages do not show up in the resulting markup. this makes my links via IDs fail, and generate strange requests that dont exist to the server.

can you share some insight to how you solved this?

Martin said...

Hi Gunnar,

very interesting post. ATM I am trying to integrate a mobile interface for an OpenSource project which uses Spring and SiteMesh as you do.
So could you write a blog post and go a bit deeper into that topic?

Cheers
Martin

Gunnar Hillert said...

Hi Martin,

Just FYI - SiteMesh has some issue regarding restful URLs as SiteMesh only sees the Servlet Path. E.g. you set your Spring MVC servlet to "/" then SiteMesh does not see "/users/1".

Also, take a look at SiteMesh 3 (https://github.com/sitemesh/sitemesh3) - is a bit easier to use. I created a fork on GitHub that, at least for me, fixes the path issues.

https://github.com/ghillert/sitemesh3

vbose said...

Can you post the sample source code in a zip file?

Zo said...

Gunnar, have you got a way to achieve the same effect with SiteMesh3? No more DecoratorMapper in 3...

sam said...

Hi...just a basic question...my application is on spring 2.5..Can i use Spring Mobile for device detection ?
if no...please guide on device detection in spring 2.5.