I’m experimenting with Spring Mobile but I can’t seem to get the basic example working. I have a feeling I’m missing something stupidly simple but I can’t figure out what it is. Here is what I have in place…
In web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>deviceResolverRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In applicationContext.xml
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:device="http://www.springframework.org/schema/mobile/device"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mobile/device
http://www.springframework.org/schema/mobile/device/spring-mobile-device-1.0.xsd">
<!-- Interceptors that execute common control logic across multiple requests -->
<interceptors>
<!-- Detects the client's Device -->
<beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
</interceptors>
</beans:beans>
In my Java class:
public class TestAction extends ActionSupport implements ServletRequestAware {
// So that we can lookup the current Device
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public String execute() {
Device currentDevice = DeviceUtils.getCurrentDevice(request);
if (currentDevice.isMobile()) // <-- fails here with NPE
Why is the device not set and resulting as null?
EDIT:
Log files seem to indicate a problem with setting the interceptor but I’m still not sure where I went wrong.
2012-05-29 09:36:36,696 DEBUG [ConstructorResolver.java:201] :
Ignoring constructor [public
org.springframework.web.servlet.handler.MappedInterceptor(java.lang.String[],org.springframework.web.context.request.WebRequestInterceptor)]
of bean ‘org.springframework.web.servlet.handler.MappedInterceptor#0’:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
‘org.springframework.web.servlet.handler.MappedInterceptor#0’:
Unsatisfied dependency expressed through constructor argument with
index 1 of type
[org.springframework.web.context.request.WebRequestInterceptor]: Could
not convert constructor argument value of type
[org.springframework.mobile.device.DeviceResolverHandlerInterceptor]
to required type
[org.springframework.web.context.request.WebRequestInterceptor]:
Failed to convert value of type
‘org.springframework.mobile.device.DeviceResolverHandlerInterceptor’
to required type
‘org.springframework.web.context.request.WebRequestInterceptor’;
nested exception is java.lang.IllegalStateException: Cannot convert
value of type
[org.springframework.mobile.device.DeviceResolverHandlerInterceptor]
to required type
[org.springframework.web.context.request.WebRequestInterceptor]: no
matching editors or conversion strategy found
I’ve had a look at this and managed to get it to work myself. So I have a few comments.
1a) I don’t think both the Filter and the Interceptor are required. I’ve just used the Filter and that was enough.
1b) The Interceptor (if used) should be configured in a
DispatcherServletxml config file. You look like you are using Struts from the use ofActionSupport, is this correct? If so, you (probably) won’t have aDispatcherServletand therefore I don’t think this config will work as expected. I think that’s why you’re getting the stack trace.2) I would add a breakpoint to
org.springframework.mobile.device.DeviceResolverRequestFilter.doFilterInternalto make sure it’s being executed.3) I would check that Struts isn’t doing something ‘funny’ with the
ServletRequest, and hiding the “currentDevice” request attribute from you somehow. In fact, I would port your code to vanilla Spring if possible.4) Maybe you could use
ServletActionContext.getRequestin yourexecutemethod and see if that works, and/or compare the returned request to that set insetServletRequest.Using Spring MVC, this is what works for me. My project is called spring-mobile-test, and “spring-mobile-test” is its context root:
web.xml:
applicationContext.xml is empty.
mvc-servlet.xml:
temp.TestController:
The browser shows the following text when I browse to the URL
http://localhost/spring-mobile-test/mvc/: