Spring integration

Spring resource handling

Spring 4.1 exposes a pluggable API allowing to specify custom web resources resolution and transformation. WUIC provides an extension that comes with:

  • a PathResourceResolver that process your workflow and wraps the resulting nut in a spring resource.

  • a VersionStrategy to build public URLs with WUIC which includes in the URL a CRC32 content based hash or the last-modified timestamp regarding your DAO configuration

Maven dependency

First you need to add to your pom.xml the maven dependency:

    <dependency>
        <groupId>com.github.wuic.extensions</groupId>
        <artifactId>wuic-spring</artifactId>
        <version>${wuic.version}</version>
    </dependency>

Integrate WUIC resolvers

Spring offers an easy way to configure resource handling with Java Config.

First, declare your @Configuration class as usual.

    @Configuration
    @EnableWebMvc
    public class MyWebConfig extends WebMvcConfigurerAdapter {

    }

Then create the WuicFacade to expose it as a bean in the ApplicationContext.

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public WuicFacade wuicFacade() throws WuicException {
        return new WuicFacadeBuilder()
                .contextPath("/resources/")
                .wuicXmlPath(getClass().getResource("/wuic.xml"))
                .build();
    }
Tip
you can completely ignore the use of wuic.xml and configure WUIC with Java Config.

Finally, just use the handy WuicHandlerMapping to inject to spring a bean handling resources with WUIC. Core resolvers are WuicPathResourceResolver and WuicVersionStrategy, but you can create additional implementations.

    @Bean
    public SimpleUrlHandlerMapping handleWuicResources(final ServletContext servletContext,
                                                       final ResourceUrlProvider resourceUrlProvider,
                                                       final WuicFacade wuicFacade) {
        final ResourceResolver versionResourceResolver =
                new VersionResourceResolver().addVersionStrategy(new WuicVersionStrategy(), "/**/*");

        final ResourceResolver pathResourceResolver =
                new WuicPathResourceResolver(applicationContext.getBean(WuicFacade.class));

        return new WuicHandlerMapping(applicationContext,
                servletContext,
                resourceUrlProvider,
                wuicFacade,
                Arrays.asList(versionResourceResolver, pathResourceResolver),
                Collections.<ResourceTransformer>emptyList());
    }

You can also override addResourceHandlers method to configure resolvers/transformers outside WUIC.

    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        final ResourceResolver myResolver = new MyResourceResolver();
        registry.addResourceHandler("/other/**")
                .resourceChain(true)
                .addResolver(myResolver);
    }

Full example

A full example is available here. In addition, it shows how you can mix built-in spring resolvers with WUIC and how to handle public URLs with Thymeleaf.

AngularJS

Feature

WUIC provides out of the box an AngularJS support and optimize the templateUrl option by default! This topic gives you the details.

Writing your directives

AngularJS is MV* framework which advises the use of custom directives. As described in the documentation:

Best Practice: Unless your template is very small, it’s typically better to break it apart into its own HTML file and load it with the templateUrl option.

This means that when AngularJS will instantiate the directive, an additional HTTP request will be executed to load the template content. This leads to two issues:

  • the user must waits the HTTP request is done to see the content displayed

  • you should take care of client cache, which must be burst each time you deploy a new version with a different template

Inlining

WUIC takes care of templateUrl occurrences in javascript code and replace it with a template option.

For example, imagine you have the following directory tree:

    .
    |--app
       |--myFeature
          |--directive
             `-- myDirective.js
          |--template
             `-- myTemplate.html

myTemplate.html:

    <h1>My Template  Title</h1>

In your myDirective.js file, you can refer myTemplate.html with an URL relative to your script location:

    myModule.directive('myDirective', function() {
       return {
           templateUrl: '../template/myTemplate.html'
       };
    });

When WUIC parses myTemplate.js, you will obtain something like that:

    myModule.directive('myDirective', function() {
       return {
           template: '<h1>My Template  Title</h1>'
       };
    });

WUIC solves two issues:

  • You save the additional HTTP request

  • As each file processed by WUIC is served with a different URL each time the content change, you make sure the client cache is burst when you update the template

Best effort

Note that in best effort mode, WUIC serves the content as fast as possible and just rewrite the template URL, without running inlining process.

Natural Templating

If you want to mix natural templating and WUIC’s AngularJS optimization feature, you must read this important page.

Typescript integration

The tsc command

Typescript could be installed in several ways. If you are a Node.JS user, then you will be able to compile your source files with the 'tsc' command:

Examples: tsc hello.ts
          tsc --out file.js file.ts
          tsc @args.txt

Many options are available, like specifying the ECMAScript version or the sourcemap generation.

WUIC comes with an extension which is able to compile typescript files. The extension works in two modes:

  • executing the tsc command, which is faster but requires to install the module with Node.JS

  • executing a compiler wrapper on top of rhino, which is slower but crossplatform

Configuration

First of all, you need to add the dependency to your project:

<dependency>
    <groupId>com.github.wuic.extensions</groupId>
    <artifactId>wuic-typescript</artifactId>
    <version>${wuic.version}</version>
</dependency>

Then, you can write your HTML page by referencing your scripts:

<script src="greeter.ts"></script>
<script src="use.greeter.ts"></script>

Then you can just include the HTML page in the WUIC process, for instance by declaring it in your wuic.xml file or just filtering it with the servlet filter.

When WUIC transforms the HTML page, it replaces the initial referenced typescript file by the compiled javascript file:

<script src="/wuic/56321344/myWorkflow/aggregate.ts.js"></script>

WUIC also serves a sourcemap file referenced in the compiled javascript.

Crossplatform configuration

By default, you don’t need to install Node.JS to compile your typescript source files with WUIC. The extension takes advantage from the tsc wrapper project, which is run with trireme, a Node.JS compatibility layer for the JVM.

However, because trireme uses Rhino to executes javascript code, the compilation is slow, even with the optimizations provided by the project. This is not really a problem because compilation is performed at build time or when the server starts at runtime, but in development you need to compile each time you change your sources. In this case you might need to enable command line execution.

tsc command line execution

The tsc command line compiles your sources 10x faster than rhino-based compiler and could be very useful when you need to recompile your scripts in development.

Before switching to this mode, you need to install the typescript compiler:

npm install -g typescript

Then, just set the c.g.wuic.engine.useNodeJs setting to true in the TypescriptConverterEngineBuilder. For instance, if you configure engines in your wuic.xml, you will write this:

<engine-builders>
    <engine-builder type="TypescriptConverterEngineBuilder">
        <properties>
            <property key="c.g.wuic.engine.useNodeJs">true</property>
        </properties>
    </engine-builder>
</engine-builders>

Note: you can filter the value with maven to set this setting to true only in a development profile. When you’ll go in production, the setting will be false and you won’t need to ask your ops to install Node.JS

Command lines execution

Purpose

Sometimes you have a command line tool that just does a part of the work as you want. When using WUIC, you can be in a situation where you would like to integrate the result of any command line execution inside the WUIC workflow. For instance, let’s imagine that you have a command line that converts LESS files to CSS.

This tutorial will show you how to configure this kind of command line to be executed by WUIC.

Command line configuration

WUIC relies on a special engine to execute command line called CommandLineConverterEngine. By default, this engine does nothing until you configure it to specifies which NutType need to be processed by the engine and which NutType is expected as the result of command line execution.

To specify to the NutType, you need to configure the c.g.wuic.engine.inputNutType and c.g.wuic.engine.outputNutType properties. For instance, you can do it in your wuic.properties file like this:

c.g.wuic.engine.inputNutType=LESS
c.g.wuic.engine.outputNutType=CSS

The value must be a supported NutType name.

At this moment, the engine will be activated and validate the command line to execute. This command line also have to be configured with a dedicated property.

c.g.wuic.engine.command=mycmd param1 param2

WUIC will use this command line to specify where the result and the associated source map should be generated according to a set of files to be converted. When analyzing the command line, WUIC will need to identify three mandatory tokens:

  • %paths%: the token to replace with the input files location

  • %outPath%: the token to replace with the result file location

  • %sourceMap%: the token to replace with the source map file location

WUIC will reject your command line if those three tokens are not defined. A valid command looks like this:

c.g.wuic.engine.command=mycmd %paths% --sourcemap %sourceMap% > %outPath%

When executing the command line, WUIC will use this pattern to contextualize a command. For instance, the command that is actually run could looks like this: mycmd /path/to/foo.less /path/to/bar.less --sourcemap /path/to/aggregate.css.map > /path/to/aggregate.css

Tip
Optionally, you can define the %basePath% token in your command line to let WUIC use a command which looks like mycmd %paths% --baseDir %basePath% --sourcemap %sourceMap% > %outPath% to execute a command which will looks like mycmd foo.less bar.less --baseDir /path/to --sourcemap /path/to/aggregate.css.map > /path/to/aggregate.css
Tip
by default all file paths are separated by a space, but you can configure it thanks to the c.g.wuic.engine.pathSeparator property.

If you need to include any additional file in the directory where the command line is executed, you can use the c.g.wuic.engine.libraries property to specify all files path to be copied separated by a semi-colon. The files paths path must corresponds to a resource available in from the classpath.

c.g.wuic.engine.libraries=/path/to/lib1;/path/to/lib2;/path/to/lib3
Tip
if any token (paths, out paths, source map path or base path) need to be specified in a separate file, you can add it to the file and then consider it as a library to be copied by WUIC. During copy, WUIC will take care of any token to be replaced. If a mandatory token is found in one library, WUIC won’t fails if this token is not in the configured command.

Using NodeJS with NPM command line

When you need to run npm on top of NodeJs as a command line run by WUIC, you must be sure that npm will be recognized in the working directory. To provide integration facilities of npm command line execution, you can install in your pom.xml file an extension provided by WUIC:

<dependency>
    <artifactId>wuic-extensions</artifactId>
    <groupId>com.github.wuic.extensions</groupId>
    <version>${wuic.version}</version>
</dependency>

This extension provides an inspector automatically detected and installed by WUIC that relies on the frontend-plugin-core module to download NodeJs and NPM in the working directory of any CommandLineConverterEngine.

In your classpath, you just have to create a file called /com.github.wuic.nodejs.NodeJsInspector.config.json that provides the information required by the frontend-plugin-core. The minimal configuration that you need to provide must contain the NodeJs and NPM version to be used. This configuration looks like this:

{
    "nodeVersion": "v0.10.30",
    "npmVersion": "1.4.21"
}
Caution
the nodeVersion value must starts with v character, while it’s not required for npmVersion.

According to the documentation here, you can also consider to specify additional configurations:

  • nodeDownloadRoot: a different URL for NodeJs archives location

  • npmDownloadRoot: a different URL for NPM archives location

  • proxies: an array of proxies to use where each element is an object which looks like {"id":xxx, "protocol": xxx, "host": xxx, "username": xxx, "password": xxx, "nonProxyHosts": xxx}

Enable HTTP/2

Purpose

This tutorial shows how you can enable HTTP/2 in your server to let WUIC use this protocol.

HTTP/2 protocol specifies the server-push feature that allows to send over the HTTP response additional resources that the client should require one he fetched the response. For instance, if a browser fetches a HTML content, it will load additional resources like CSS or Javascript files. Actually, we don’t wait the browser performs a new request and we push those resources earlier.

This method is speculative because we don’t know that the client will really load the resource. For instance, if the resource is in the browser cache, then the push will be canceled.

Tip
by default, WUIC uses resource-hints to let the browser fetch the resources once the HTTP response is sent to the client. This is slower than HTTP/2 server-push but not speculative: if the resource is in the browser cache no unnecessary download will occur. If you enable HTTP/2, then server-push will be used instead of resource-hints.

Java server

Java server and even servlet containers don’t implement any standard API for HTTP/2. This means that each server comes with its own API that you need to specifically implement. WUIC hides those API and comes with a support for a specific server under the form of a JAR file.

Servlet containers

For any servlet container, you must install the com.github.wuic.servlet.HtmlParserFilter to let WUIC initiate a server-push for resources associated to the filtered HTML page.

Jetty

First you need to install HTTP/2 with Jetty. This requires the version 9.3+ and the JDK 8. You will find a complete sample in this pom.xml.

Then, you just need to add the dependency corresponding to the Jetty support for WUIC:

<dependency>
    <groupId>com.github.wuic.extensions</groupId>
    <artifactId>http2-jetty</artifactId>
    <version>${project.version}</version>
</dependency>

You can run your application and see that HTTP/2 is transparently enabled. To see if everything is fine, we advise to check the session activity for your host by opening link:chrome://net-internals/#spdy in chrome.

Any WUIC sample can be run with HTTP/2. Read the README.md for details!

HTTP/2 and nghttpx

With nghttpx installed as a proxy, WUIC can initiate a HTTP/2 server-push without any extra HTTP/2 installation in your java server!

This interesting and alternative technique is to let a nghttpx proxy to negotiate a HTTP/2 connection with browsers and initiate server-push according to the header specified in the HTTP response sent from the back-end. nghttpx pushes resources referenced in the <link> header found in the proxied HTTP response. See their documentation for more details here.

The good news is that WUIC specifies by default <link> headers in the HTTP response when a HTML page is filtered by the com.github.wuic.servlet.HtmlParserFilter. Consequently you just have to install this listener in your webapp without the need to configure HTTP/2 in your servlet container.

Natural templating with AngularJS

Purpose

This part explain an important design consideration when you want to mix natural templating, WUIC and AngularJS. In fact, WUIC reads templateUrl option relatively to the script location declaring the directive, while in a pure HTML page, AngularJS loads it relatively to the page location. This chapter gives details about the workaround you can use to mix natural templating in development and server-side WUIC optimization in production.

Design

Natural templating considers you should not process your page on server side before it could be served to the client. WUIC makes it possible since you can write a pure HTML page and then optimize it with an engine installed by default. The simplest way to optimize the page in this case is to use the servlet filter provided by WUIC.

Demonstration

If you want to directly display the HTML page in the browser, your templates will be loaded relatively to this page. For instance, if we have the following structure:

    .
    |--app
       `-- index.html
       |--myFeature
          |--directive
             `-- myDirective.js
          |--template
             `-- myTemplate.html

You will write your directive like this:

    myModule.directive('myDirective', function() {
       return {
           templateUrl: 'myFeature/template/myTemplate.html'
       };
    });

Everything will work fine. Then if you want to use the servlet filter provided by WUIC. When you deploy into production, WUIC will try to detect templateUrl options in the javascript code. In our example, WUIC will read the URL myFeature/template/myTemplate.html relatively to the script myDirective.js, which leads to bad URL computation (/app/myFeature/myDirective/myFeature/template/myTemplate.html does not exists!). In that case, WUIC will log a warning and won’t change the statement. Your application won’t be broken but no optimization will be done!

So if you want to see your template optimized, you should write your directive like this:

    myModule.directive('myDirective', function() {
       return {
           templateUrl: '../template/myTemplate.html'
       };
    });

The problem is that your template won’t work when you display your page without filtering it with WUIC. In fact, because the URL is relative to the page location, the browser will try to load /app/../template/myTemplate.html, which does not exists! The solution is to provide a function which takes in parameter the relative URL and computes the correct absolute path like WUIC does. This could be done with a function returning the location of the current executed script. You can bind this function to the declared module:

var myModule = angular.modue('myModule');

/**
 * Gets the directory path (url without file name) from the latest loaded script.
 * This function could be used to register script location when they get executed.
 * In fact the returned object exposes a getChild function which returns a given path
 * concatenated to the script directory path.
 *
 * @method getPathRelativeToScript
 * @returns {Object} the directory path
 */
myModule.getLastScriptPathDirectory = function () {
    var scripts = document.getElementsByTagName('script');
    var path = scripts[scripts.length - 1].src.split('?')[0]; // remove any ?query
    var dir = path.split('/').slice(0, -1).join('/') + '/';   // remove last filename part of path

    return {
        getChild : function(path) {
            return dir + path;
        }
    }
};

Then in your myDirective.js file, you can use this function like that:

    1. myModule.constant('myDirectiveUrl', myModule.getLastScriptPathDirectory());
    2. myModule.directive('myDirective', function(myDirectiveUrl) {
    3.    var getChild = myDirectiveUrl.getChild;
          return {
    4.        templateUrl: getChild('../template/myTemplate.html')
          };
       });
  1. We declare the AngularJS constant which to keep the script location.

  2. We inject the constant into the directive.

  3. The constant is an object providing a getChild function.

  4. We use the getChild function to get the correct absolute URL.

The last thing we have to do is to configure WUIC to not extract getChild(…​) as an URL and instead ignore the wrapping function. This could be done by configuring the JavascriptInspectorEngine in your wuic.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<wuic>
    <engine-builders>
        <engine-builder id="wuicDefaultJavascriptInspectorEngineBuilder" type="JavascriptInspectorEngineBuilder">
            <properties>
                <property key="c.g.wuic.engine.wrapPattern">getChild(%s)</property>
            </properties>
        </engine-builder>
    </engine-builders>
</wuic>

That’s it! you can now develop without any server deployment and then let WUIC optimize your scripts in production!