Authors

Monday, July 9, 2012

Jangaroo is not only about ActionScript-to-JavaScript compilation, but generally about providing free, Open Sourcetools for Enterprise Web Developers. So today's about a small tool we just added to the stack that integrates assembly of CSS sprites into your Maven build process.

You may
have heard or even used SmartSprites (http://csssprites.org) by Carrot Search / Stanislaw Osinski.
A small tool that lets you bundle your images into sprite sheets improving your
webapp's performance.

Using SmartSprites
from over and over again, it can be tedious to always start the process manually. Since
we aren't using Ant but Maven more regularly we thought about a slim Maven
integration. While SmartSprites does offer a Maven artifact, we only found an outdated, unfinished Maven plugin to actually apply SmartSprites as part of a Maven build, and so came up with something ourselves.

We arrived at a working first version (in fact it's 1.5 1.8 by now) of such a plugin. It can surely be improved further, but working well for our needs.

You could
leave out the configuration part completely and default values would be used.
Following you’ll find the complete configuration guide. As all configuration attributes follow their SmartSprites counterparts closely, the description can be taken directly from the SmartSprites documentation.Below you will find the correct camel case annotation and their default values if given.

<documentRootDirPath>

<logLevel>

<spritePngDepth>

<spritePngIeSix>

<cssFileEncoding>

<cssFileSuffix>

What about a demo
application?

Please find
a demo application on github showing you how to bundle your sprites in a webapp.
It is a small example just showing you how to integrate the
SmartSprites-Maven-Plugin into a webapp.

The example
is rather straightforward so you just might want to take a look at the
following files:

pom.xml

line
23-40 for the SmartSprites part

line
42-53 copy the generated ressources

line
55-69 Jetty

src/main/webapp/index.jsp

divs for showing the images, line 16-21

src/main/sprites/css/flags.css

css configuration part

The other
files are just for making this example look a bit nicer.Since we use the SmartSprites Maven plugin ourselves for building an Enterprise software product, it will be maintained for quite a while. So feel free to use it, too, and please don't hesitate to give feedback either here or at the Jangaroo user's group!

Friday, June 8, 2012

Jangaroo's mission is to create and apply Enterprise software development tools to Web development. While Jangaroo is known for its ActionScript-to-JavaScript compiler jooc, we also care about "native" JavaScript development. In the process of creating a Maven-based build process for compiled ActionScript, we were baffled that there was not even a Maven-based build process for JavaScript. In fact, there is no version-, dependency- and artifact-managing build process for JavaScript at all (as far as we know).

In the course of creating Jangaroo 2, and utilizing a new feature of Java Servlet 3, we can now present a light-weight and easy way to use Maven for managing JavaScript library versions and their dependencies and adding them to your Web application.

Approach and Related Work

Note that we are not the only ones who provide Maven JAR artifacts containing repackaged JavaScript libraries. Independently, James Ward created a project called WebJars, which does something quite similar as proposed here. He also uses JARs and Maven, but the difference is that he is targeting other Web servers and languages, essentially using the JAR as a ZIP. Our approach is to use the Servlet 3 JAR layout, essentially putting all Web resources under the path META-INF/resources. The main advantage is that every Servlet 3 compliant application server (Jetty 8, Tomcat 7, Glassfish 3, Resin 4, WebSphere 8, WebLogic 12) understands this standardized format (JSR-315) immediately without any plugin, Servlet or other extension. Another benefit is that you can add files to the JAR that are not supposed to be Web resources, e.g. other meta data and of course Java classes, so that you could for example unite code implementing the client- and server-part of some service in a single JAR.

An organizational advantage we have over James' artifacts is that we deploy all repackaged artifacts of Open Source libraries (almost all JavaScript libraries are Open Source!) directly to the Maven Central repository, saving you the need to add <repository> sections to your Maven POM and leaving you independent from our Maven repository being online.

Try It Out!

The first available artifact is a repackaging of Ext JS 3.4.0 (yes, it is an old version, but take it as an example of the mechanism) and a very light-weight example project using this artifact. The following steps are needed once to have an environment to develop Maven-managed JavaScript Web applications:

Then, all you need to do is build the project (which downloads all needed stuff from Maven Central when invoked for the first time) and start a Jetty Web server via Maven, simply via> mvn jetty:start
The default port is 8080, so you can watch the resulting Web app in any browser using http://localhost:8080. To prove that Ext JS has been loaded and works, the app just opens an Ext alert box.

Only three small text files are needed to

download the desired Ext JS library,

download Jetty webserver,

configure Jetty to serve the contents of the Ext JS library and the local project resources, and

After the inevitable XML header (which is always the same), every Maven project model needs to specify a unique combination of groupId and artifactId, and a version. For this test project, they really do not matter, since the generated artifact will never be deployed to a repository. The packaging type war tells Maven that we are building a Web application (Java terminology: Web ARchive). name and description are just for human readability.

The only plugin that needs to be mentioned explicitly is jetty-maven-plugin, and you also need to specify the exact version you want to use. Well, it's still only a couple of lines to download and start a Web server, isn't it?

To download a serve all Ext JS 3.4.0 resources, a simple dependency suffices, thanks to the standard-conform JAR layout and central deployment of the artifact.

index.html is the simplest HTML page you could think of that starts an Ext JS application. The only interesting thing here is how the resource paths have been chosen, because you do not actually "see" the Ext JS resources―they are hidden in a JAR somewhere in your local Maven repository (see below). For every JavaScript library repackaging, we have to agree upon a standard path where it is served in the Web application. For Ext JS, we chose /ext-js/ as the base path. The file structure below this base path is exactly as in the ZIP that can be obtained from Sencha's Ext JS 3 download page.

web.xml is only needed to disable a Jetty feature ("file locking") that hinders development, and to satisfy the Maven WAR plugin, which would have to be configured to not <failOnMissingWebXml> otherwise.

The Jetty Maven plugin configures Jetty in a clever way: library dependencies like Ext JS, which have been downloaded to your local Maven repository automatically (usually ~/.m2/repository), are served directly from that JAR. That means no files are extracted, not even the JARs needed by your Web app are copied. All local project Web resources are taken directly from src/main/webapp. Try changing index.html (e.g. the alert message) and reload in the browser: it works without further build or deployment!

If you want a complete Web app that could be deployed into a remote Java application server, you can invoke mvn package, and a directory target/webjars-extjs-example-0.1-SNAPSHOT is created which contains all needed resources. This directory is also zipped as target/webjars-extjs-example-0.1-SNAPSHOT.war.

Unpacking all Web resources contained in JARs, e.g. to deploy them to a static Web server like Apache HTTP Server, is also possible via Maven, but I'll cover that in a later update.

Mighty Maven

What the simple example does not show is that, if ext-js 3.4.0 had a dependency on some other artifact, say ext-core 1.0, you wouldn't have to care about it. Simply specifying a dependency on ext-js lets Maven collect all transitive dependencies and add the corresponding artifacts to your Web application. Furthermore, if two libraries you use depend upon the same third library, Maven takes care of the third library being included only once, and offers dependency management to resolve possible version conflicts.

All in all, given the complexity of the problem it solves, Maven provides a light-weight way to manage complex JavaScript Web applications, making it easy to keep track of libraries used, their versions, and their dependencies. Furthermore, Java Servlet 3 helps structure a Web application as a composite of modules instead of a huge bunch of files, which speeds up build process and test system start-up.

What Next?

Next is to repackage and deploy or release several JavaScript libraries. There are several options, so here we need your vote and maybe even your help. We plan to repackage the libraries and versions we (plan to) use at CoreMedia, for example jQuery 1.7, Ext JS 4.1.0, RequireJS 2.0.1, and CKEditor 3.6.2. If you need other JavaScript libraries or other versions, you can simply create an issue at JooTrack/LIBS. We need the exact location of a download package or all single download links, and if you could provide additional information which files are usually needed in an actual deployment (e.g. no examples, no documentation, ...), it would help a lot. So start refactoring your large-scale JavaScript project today―clean up the JavaScript mess!

Monday, January 30, 2012

Let's continue the series on simulating ActionScript language features in JavaScript with something similar to optional parameters, namely the ... (rest) parameter.
ActionScript allows you to specify that an arbitrary number of parameters follow the usual named and optional parameters by prefixing the last parameter with three dots (see "The ... (rest) parameter"):

As you can see, all formal parameters following the named parameters are combined into an array. Since the ... (rest) parameter is always of type Array, you can safely skip the type annotation.

The arguments variable in JavaScript
Fortunately, JavaScript offers access to all formal parameters of a function call, even if they are not declared as named parameters of the function, through the arguments variable. For some reason, this variable does not actually hold an Array. Instead, it is an array-like Object with indexed properties and a length property. This means that we cannot invoke Array methods directly on arguments, but there is a trick: Call the slice function retrieved from the Array prototype, as described e.g. here, and the result is a "real" Array:

Array.prototype.slice.call(arguments)

At the same time, we can cut off the named parameters, since the first parameter to slice is the index where to start slicing from the source array. Thus, the resulting JavaScript code generated by the Jangaroo compiler jooc is the following:

Note the slice parameter value 2, which takes care of cutting off the two named parameters. Also note how Jangaroo only adds an auxiliary statement, but keeps all other statements exactly the same, which makes debugging a lot easier.

Side note: arguments is an array is AS3
The only thing Jangaroo currently does not yet implement correctly is that in ActionScript, the arguments variable is actually always an array! Thus, instead of writing

1 public function joinComma() { 2 return arguments.join(","); 3 }

which would be fine in ActionScript, in Jangaroo you currently have to use

1 public function joinComma(...args) { 2 return args.join(","); 3 }

This is to save the overhead of always converting arguments into an array. Of course, the compiler could analyze whether arguments is used as an Array at all and only add the conversion code then. I just filed the bug as issue JOO-12.

Saturday, January 28, 2012

To continue our series on simulating ActionScript language features in JavaScript, this episode is about parameter default values.
In contrast to JavaScript, ActionScript allows to specify a default value for a function (or method) parameter, like so:

1 public function insult(s = "fool") { 2 return "you " + s; 3 }

The idea is that when the method is called without providing a value for parameter s, the default value "fool" will be used. Details on what additional rules hold for declaring parameter default values are given in the Adobe documentation on function parameters and a bit less reference-like e.g. in a tutorial on Ntt.CC.

Why, it's easy, isn't it?
A straight-forward implementation in JavaScript (similar to the solution suggested by Bernd Paradies for FalconJS) would be to replace undefined paramter values by their default value:

because in JavaScript, undefined may be redefined, but anybody who does so is, excuse me, a fool.)

In JavaScript, when you omit a parameter when calling a function, the parameter value indeed is undefined. But it is a fallacy to assume that everyundefined parameter must be replaced by its default value! Consider the following ActionScript class:

What do you think will be traced? Try it out, and you'll see that explicitly handing in undefined does not trigger the default value! Thus, the result is

1. you nerd

2. you fool

3. you undefined

(Careful, never call a JavaScript programmer "you undefined"!)

Using the straight-forward JavaScript implementation, the result would be

1. you nerd

2. you fool

3. you fool

As you can see, using parameter default values depends on the number of formal arguments, not on their value. This is the reason why they are also called optional parameters, and why after a parameter with a default value, all following parameters must also specify a default value.

Getting it right

Thus, the correct JavaScript equivalent (as generated by the Jangaroo compiler jooc) is to check the number of formal parameters. Fortunately, this can be realized by checking arguments.length:

In fact, this solution even provides better runtime performance when using multiple optional parameters, since multiple arguments.length checks can be nested, while the undefined checks in the straight-forward solution would be sequential. Consider the following example:

At first sight, this solution seems more efficient, because arguments.length is only evaluated once. The reason why we still chose the nested if code layout is that the switch solution becomes either long or non-robust when using many non-optional parameters. Note the lines case 0: and case 1: in the example above: although the method should never be called with less than two parameters (since the first two are not optional), we want to handle that case, too, since Jangaroo code may be called from JavaScript, where no function signature check is performed. When the function is called with fewer parameters than required, you would still expect the default values to pop in. So the case statements would pile up when there are many non-optional parameters. However, I could imagine a mixed solution like the following: