Webjars-locator doesn't work with XML based Spring MVC 4.2.x configuration?

Viewed 1713

I have a Spring MVC 4.2.x project. I am configuring it via XML based configuration file:

<servlet>
    <servlet-name>foo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

In the context.xml file I have configured resources and annotation-driven mode:

<mvc:resources mapping="/webjars/**" location="/webjars/"/>
<mvc:annotation-driven/>

Everything works fine except the one thing: webjars-locator - Webjars locator doesn't work at all.


I've started look into the Spring MVC sources to understand what's going wrong, and found, that webjars-locator works through WebJarsResourceResolver class, which's object is added in the ResourceChainRegistration.getResourceResolvers() class method.

The full sequence looks like:

WebMvcConfigurationSupport.resourceHandlerMapping() >> ResourceHandlerRegistration.getHandlerMapping() >> ResourceHandlerRegistration.getRequestHandler() >> ResourceChainRegistration.getResourceResolvers(), where it is added as:

if (isWebJarsAssetLocatorPresent) {
    result.add(new WebJarsResourceResolver());
}

The problem, is that in case of XML based configuration described above, this sequence is not invoked, neither WebMvcConfigurationSupport class is used.

Furthermore, if I add

@EnableWebMvc
@Configuration
public class WebConfig {
}

into project, WebMvcConfigurationSupport obviously works, but in ResourceHandlerRegistration.getHandlerMapping():

protected AbstractHandlerMapping getHandlerMapping() {
    if (registrations.isEmpty()) {
        return null;
    }
...
}

registrations is empty!


After all, the only one way how to forcibly make Spring to add WebJarsResourceResolver into the resolver chain, is:

1) remove <mvc:resources mapping="/webjars/**" location="/webjars/"/> from the context.xml and

2) add addResourceHandlers into WebConfig:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry
            .addResourceHandler("/webjars/**")
            .addResourceLocations("/webjars/")
            .setCachePeriod(3600)
            .resourceChain(true)  // !!! very important
    ;
}

My question is: what am I doing wrong? Why XML bases configuration doesn't cause WebJarsResourceResolver to be registered?

2 Answers

To answer your remaining question "why it isn't described in webjar documentation":

It is/was an issue that has been reported on May 3, 2016:

https://github.com/webjars/webjars/issues/1395

As described on this page this issue also mentions that Spring MVC requires the resourceChain() method. I created a PR today to fix the issue:

https://github.com/webjars/webjars/pull/1946

FYI: I tried to get version agnostic url's working the way it was described in the documentation but didn't succeed. Along the way I also found the following issue that mentions that "The resourceChain() method must be called for version-agnostic WebJars":

https://github.com/spring-projects/spring-framework/issues/25410

Related