2015-05-09, Sven Ehrke (@syendar)

Let’s say you want use what I call a web artifact library such as bootstrap in your Java based webapplication. Bootstrap’s Getting started guide describes how you could use it directly from the proposed CDN or via tools like bower or npm.

In this post I would like to show you another possibility: webjars.

First I will describe how to use it and then give some background information.

Usage

Spring Boot

You can find the source for this example on Github.

To add bootstrap as a webjar to your Spring Boot projects simply add the following dependency to your build file:

build.gradle
dependencies {
  compile 'org.webjars:bootstrap:3.3.1'
}

For maven it would be:

pom.xml
<dependency>
  <groupId>org.webjars</groupId>
  <artifactId>bootstrap</artifactId>
  <version>3.3.1</version>
</dependency>

Now when you start your application and point your browser to http://localhost:8080/webjars/bootstrap/3.3.1/css/bootstrap.css you should see bootstrap’s css in the browser. This means that in your html files you can these links to access bootstrap:

<link rel="stylesheet" href="/webjars/bootstrap/3.3.1/css/bootstrap.min.css">
<script src="/webjars/bootstrap/3.3.1/js/bootstrap.min.js"></script>

Grails 3

Since Grails 3 is based upon Spring Boot you only need to add the bootstrap webjar dependency to your build.gradle as described in the previous section. Everything else also works exactly the same.

Grails 2

For Grails 2 I could not get it running out of the box using the servlet 3 approach. Anyway here are my attempts so far:

Assume you named your grails application grails244_webjar and thus you can access it from http://localhost:8080/grails244_webjar/.

When you add the compile 'org.webjars:bootstrap:3.3.1' dependency to your BuildConfig.groovy and then try to access http://localhost:8080/grails244_webjar/webjars/bootstrap/3.3.1/css/bootstrap.css you will get a HTTP 404. http://localhost:8080/webjars/bootstrap/3.3.1/css/bootstrap.css did not work for me either. My guess is that it has something to do with the way the GrailsDispatcherServlet is working.

But: taking the servlet 2.x approach as described on this page works:

  • add the dependency compile 'org.webjars:webjars-servlet-2.x:1.1' to your BuildConfig.groovy

  • Add the WebjarServlet to web.xml (first you need to invoke grails install-templates to get a web.xml) and add the following to it:

src/templates/war/web.xml
<servlet>
  <servlet-name>WebjarsServlet</servlet-name>
  <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>WebjarsServlet</servlet-name>
  <url-pattern>/webjars/*</url-pattern>
</servlet-mapping>

(See also Additional Notes)

Background

A webjar is nothing special. The only important thing to know is that since the Servlet Specification 3.0 all files underneath the path META-INF/resources are treated like static resources and can be accessed directly from the browser without having to do anything special.

Example

You take a servlet 3.0 compliant container like a modern Tomcat, Jetty, etc. Then you create a jar with a file META-INF/resources/hello.txt containing the text hello world. Now create a war file and put this jar file into WEB-INF/lib. When you start your Tomcat or Jetty and point your browser to http://localhost:8080/readme.txt it should display the text hello world.

The idea behind webjars is to package all files like css, js, images needed by the browser together in a jar file. This has the following big advantages:

Advantages

  1. You can leverage maven repositories e.g. by putting webjars into maven central or bintray as any ordinary jar file

  2. You can leverage your build tool’s (gradle, maven) dependency management support.

  3. You do not have to check in js or css files anymore and you do not have to copy these files around during at build time

  4. Because you can leverage your build tool’s dependency management support means that you can also define and use transitive dependencies for your web artifacts

Let’s take bootstrap again as an example. Note that it has a transitive dependency to jQuery. And if you have a look at the pom file of bootstrap’s webjar you can see that it has a dependency declaration on jQuery including the exact version it wants:

pom.xml (of bootstrap’s webjar)
<dependency>
  <groupId>org.webjars</groupId>
  <artifactId>jquery</artifactId>
  <version>1.11.1</version>
</dependency>

This means you only have to declare the dependency to bootstrap in your maven/gradle file and get the right jQuery webjar for free.

If you have a look at http://www.webjars.org/ you can see that webjars for many popular Javascript/css frameworks/libraries already exist and are available via maven central.

Conclusion

In my opinion using webjars is a great way to use web artifacts like Javascript and css files because it is possible to leverage the existing maven dependency management tools and it is not necessary to fiddle around with individual files.

Since I discovered webjars they are my preferred way to use web artifacts in Java based projects especially since most of the popular frameworks and libraries are already available as webjars. And even if you want to provide your own web artifacts as webjar you simply have to stick them in a jar file underneath META-INF/resources and you’re done.

Additional Notes

Modules Manager for Grails 2

For Grails 2 http://www.webjars.org/ suggests to use the Modules Manager plugin:

BuildConfig.groovy
dependencies {
   compile 'org.webjars:bootstrap:3.3.1'
}
plugins {
  compile : 'modules-manager:0.2.1'
}

Then on the commandline you need to invoke grails refresh-modules which will print something like this:

 Application cleaned.
| Created file web-app/modules/bootstrap/webjars-requirejs.js
| Created file web-app/modules/bootstrap/fonts/glyphicons-halflings-regular.eot
| Created file web-app/modules/bootstrap/fonts/glyphicons-halflings-regular.woff
| Created file web-app/modules/bootstrap/fonts/glyphicons-halflings-regular.ttf
| Created file web-app/modules/bootstrap/fonts/glyphicons-halflings-regular.svg
| Created file web-app/modules/bootstrap/less/print.less
| Created file web-app/modules/bootstrap/less/pager.less
| Created file web-app/modules/bootstrap/less/.csscomb.json
| Created file web-app/modules/bootstrap/less/scaffolding.less
| Created file web-app/modules/bootstrap/less/labels.less
| Created file web-app/modules/bootstrap/less/normalize.less
| Created file web-app/modules/bootstrap/less/carousel.less
| Created file web-app/modules/bootstrap/less/popovers.less
| Created file web-app/modules/bootstrap/less/breadcrumbs.less
| Created file web-app/modules/bootstrap/less/navs.less
...

In my case I named the application grails244_webjar. To see the bootstrap css use the following URL:

As you can see the web artifacts are copied from the jar file into the web-app/modules folder and need to be accessed from the browser like this. With this approach we benefit from the fact that web artifacts are packaged in jar files at build time but not at runtime because the META-INF/resources mechanism is not used at all.