11

I was wondering if someone has already solved this. I have a SpringMVC app and we are adding support to WebKit type mobiles (iPhone and Android basically) so I was wondering someone has found an elegant way of defining specific views depending on the client that sent the request.

I know that a simple if in a Controller implementation can do the trick, but I'm looking for something more flexible/elegant (a specific ViewResolver implementation, or an interceptor maybe).

Help will be greatly appreciated... as always =)


This is a pretty old question. What you need to do is use Spring-Mobile to achieve this in a standard elegant manner

Chepech
  • 5,258
  • 4
  • 47
  • 70
  • I think this is a good idea. I created [a JIRA issue](https://jira.springframework.org/browse/SPR-7518) for this. – earldouglas Sep 01 '10 at 23:03

4 Answers4

9

Update: look at spring-mobile

Original answer:

It would be pretty simple to create a custom ViewResolver that resolves views based on the User-Agent header.

  • here is a list of mobile user agents (page removed from wikipedia). Check the header against it, and resolve a mobile view.
  • if the user-agent is not a mobile, then return null, thus letting other resolvers resolve a view.
  • make sure your resolvers are defined (in the spring xml) in the proper order, so that the mobile resolver is consulted first.
krlmlr
  • 25,056
  • 14
  • 120
  • 217
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Ok, just one concern about this... Do I still have access to the HTTP request on the ViewResolver, If so, how do I access it without specifically passing it on each and every Controller? – Chepech Sep 02 '10 at 13:26
  • You can get the request from `RequestAtrributesHolder` (cast the attributes to `ServletRequestAttributes`) – Bozho Sep 02 '10 at 13:43
  • Yep, but that can only be done at Controller level, ViewResolver no longer get the HTTPServletRequest unless you pass it in the model, which is something that may not be desirable. – Chepech Sep 09 '10 at 17:47
  • @Chepech so you say there is nothing in `RequestAttributeHolder` in the ViewResolver? That's surprising. – Bozho Sep 09 '10 at 17:51
  • it's not :) The RequestAttributeHolder is a perfectly valid class – Bozho Sep 10 '10 at 13:41
2

Like @Bohzo and yourself already said spring-mobile is the way to go.

As of version 1.1 you can use the LiteDeviceDelegatingViewResolver to configure the type of behavior you're describing.

Device Aware View Management

http://static.springsource.org/spring-mobile/docs/current/reference/html/device.html#device-aware-view-management

Spring Mobile includes AbstractDeviceDelegatingViewResolver, an abstract ViewResolver wrapper that delegates to another view resolver implementation, allowing for resolution of device specific view names without the need for a dedicated mapping to be defined for each view. A lightweight implementation is provided, which supports adjusting view names based on whether the calling device is normal, mobile, or tablet based.

Within your application, you can then create alternate views for normal, mobile or tablet devices, and given the proper configuration, Spring Mobile will adjust the view name to resolve to the correct one. This happens internally, without the need to add conditional logic through your controllers.

Community
  • 1
  • 1
Bart
  • 17,070
  • 5
  • 61
  • 80
1

Ok I found a more specific answer. There is a problem with the solution that Bozho proposed. the fact that the ViewResolvers no longer have access to the HttpServletRequest. There is a way to access the request but its kind of dirty IMHO.

So that said, this is a very elegant and easy to implement solution. Basicly it involves a custom ViewResolver (as Bozho proposed) but it adds an handlerInterceptor that adds the User-Agent to the model so you no longer have to add it manually.

Community
  • 1
  • 1
Chepech
  • 5,258
  • 4
  • 47
  • 70
0

To access current Request inside ViewResolvers.

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
            .getRequest();
Nitin Jha
  • 1,485
  • 2
  • 10
  • 14