WebJars in Spring MVC

Last week I announced the WebJars project that allows you to specify your web libraries (JavaScript, CSS, etc) as dependencies in your Java web applications. With some help from Jeremy Grelle I was able to get a simple WebJars Spring MVC example working.

First you will need to add the WebJars repository to your build. For Maven, just add the following to your “pom.xml” build file:

    <repositories>
        <repository>
            <id>webjars</id>
            <url>http://webjars.github.com/m2</url>
        </repository>
    </repositories>

Then add a WebJar dependency, like Twitter Bootstrap:

        <dependency>
            <groupId>com.github.twitter</groupId>
            <artifactId>bootstrap</artifactId>
            <version>2.0.2</version>
        </dependency>

Then you need to add a resource handler to Spring MVC that maps requests from a given path to files in the classpath. The WebJars are all inside of a “public” directory. If you are using Java configuration in Spring then you would do the following:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
 
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
  }
}

Or if you are using XML config then add the following to your Spring config:

<mvc:resources mapping="/public/**" location="classpath:/public/"/>

Then you can reference a WebJar’s assets with something like:

<link rel='stylesheet' media='screen' href='/public/stylesheets/bootstrap.min.css'>

How easy is that? Now you are managing your web libraries as versioned dependencies and you even get transitive dependencies! Check out the full source code for this example on GitHub: https://github.com/jamesward/spring_webjars_demo

Right now there are only a couple of WebJars so if you need something else then simply request a new one via a new issue on GitHub.

Please let me know what you think about this. Thanks!

This entry was posted in Java, Spring, WebJars. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • Daniel

    Great! But my unmentionables are in a right old state. Next can you work on a library plugin for Spring MVC to manage my sock drawer?

  • nicolas de loof

    Hum, so you compensate the lack of dependency management support in maven-war-plugin for javascript / css dependencies by adding (yet another) servlet-based request handling, that will be far less efficient tnat letting apache frontend handle static resources or a CDN to deliver common javascript libraries… is this really the best option ?

    • http://www.jamesward.com James Ward

      I’d like my application to be completely self contained including the static assets.  Then if a CDN can be used to speed up access to those assets, great!  I have an example of how to set that up in an article I’m working on: https://github.com/jamesward/jaxrsbars

  • http://raibledesigns.com/ Matt Raible

    Great stuff James. 

  • Phil Webb

    Nice.  If you are not using Spring or Play and are happy with a bit more typing you can even overlay these resources directly into your WAR to access them in the classic way.

    https://gist.github.com/2560555

    It’s a shame that the maven-war-plugin does not support transitive overlays.

    • http://www.jamesward.com James Ward

      Wow!  Nice!  I didn’t know that was possible.  Thanks Phil.

    • Frank Wienberg

      I wouldn’t recommend using war overlays. The result is that web  resources would be unpacked and re-packed over and over in your build process, which is unnecessarily time- and space-consuming. Because transitive dependencies do not work, you also cannot use Maven’s dependency management—all dependencies are hard-wired in a war.As detailed in http://blog.jangaroo.net/2012/06/managing-javascript-libraries-with.html, using the Servlet 3 feature that resources can be placed under ‘META-INF/resources’ inside any jar in ‘WEB-INF/lib’, there is no need to define a controller or Servlet. You can use normal jar dependencies, which work perfectly also for the transitive case: Maven’s standard war packaging automatically collects all transitive jar dependencies in ‘WEB-INF/lib’. And you remain independent from Spring or Play—just use any up-to-date Java web server or add another step to the build process that re-packages the final Java web app into a static one (see comment in the blog post and update of the example project on github).

  • http://twitter.com/starbuxman Josh Long

    Cool stuff, James!

  • Barry Pitman

    Awesome, thanks a lot!