Hello again. I'm back in the real world with a shiny new Computer Science degree, after three grueling years of hard work. I've relocated to the SF Bay Area from Minneapolis in search of greener pastures. I accepted a position with a startup, Emota.net, and am now working with Node.js and Redis. I'm still getting on my feet out here, but I'll be resuming business as usual as I explore the Node ecosystem. Cheers!
Wednesday, June 15, 2011
Sunday, August 29, 2010
Creating a Javascript Library with Maven
A Javascript library consists of some Javascript files, and potentially some resources like images, templates, and stylesheets. In Maven, these are arranged in the following directory structure:
The one item that might require some explanation is pom.xml. It is a “project object model” file, which has information about your project and its configuration. It'll be explained piece-by-piece below.
my-library/
. pom.xml
. src/
. main/
. javascript/
. resources/
. test/
. javascript/
. resources/
Initial Steps
The first thing you need to do is install Maven. Go to http://maven.apache.org and grab a copy of 2.2.x. Extract it somewhere and add the bin directory to your path.
$ export PATH=$PATH:path/to/maven/bin && mvn --version
If that worked out right, you should see a Maven version and some Java environment information displayed.
Next you need to edit your settings.xml file. Run the following command:
$ mkdir ~/.m2 && gedit ~/.m2/settings.xml
and add this content to the file:
http://gist.github.com/557035#file_settings.xml
These settings are adding the Sonatype OSS repository where the Javascript plugin and several popular libraries that I have packaged for Maven use are hosted.
Creating the Project
All that is needed to create a Javascript library is a POM and some source code. A simple POM looks like this, and is called pom.xml:
http://gist.github.com/557035#file_pom.xml
There are a couple notes about this file, as seen in the comments above.
1. In Maven, every project is defined uniquely by these 4 pieces. groupId should be a subdomain under your control. artifactId is the name of this project. version is typically [major].[minor].[point]-[type]; type is either a “release” or a “snapshot”. This pertains to deployment which I'll cover in the next article.
2. A project has many dependencies and a few possible scopes. In this case we're using the “test” scope. The other important one is “runtime”, which I'll describe later. Each dependency has a version; is good practice to use a range. In this case we can use any 1.4.x version of jQuery. This is especially important as many dependencies are added to the project, which may all rely on different point releases of the same library.
3. Each project can have many plugins. The one that makes JS development possible is the javascript-maven-plugin. Not all plugins require the 'extensions'
Once you have your POM in place, you need to create some Javascript. Create a file called hello.js in src/main/javascript:
http://gist.github.com/557035#file_hello.js
Adding QUnit Tests
Now that we have a little functionality in place, let's create a test for it. Create suite-hello.html in src/test/javascript:
http://gist.github.com/557035#file_suite_hello.js
First, all tests match the pattern suite-*.html. Second, notice your hello.js file is in the scripts/ directory, while external dependencies (qunit and junit) are in scripts/${artifactId}/filename.js. These are conventions I have put in place that mirror web application packaging, which will be covered later.
One thing to notice is that qunit is never declared as a dependency to the project. This is likely to change in the near future. At the moment it is automatically added by the plugin code. It might be safe to declare it explicitly, but I'll leave that as an exercise to the reader.
Now run the following command:
my-library$ mvn test && cat target/surefire-reports/qunit.txt
If everything went right, you should get a message that says “Build Successful” and have a brief summary of the executed test displayed.
Next Time...
In the next article I'll show you how to release your project to an open source repository, and declare where it exists in an SCM for automatic release tagging.
Saturday, August 28, 2010
Javascript Maven Plugin Revamped
In the process of researching for the Engineering Better Javascript series, I ended up implementing some of my ideas to make them concrete. I've extended the existing Javascript Maven Tools to include a QUnit plugin and report integration, as well as added some integration tests to ensure that things are working as expected. I also added a javascript-project base parent, which takes some of the redundant code out of the POM for a Javascript project. The code is available on GitHub, here.
A good example project to check out is my ActivityStreams JS project. There are just a few things to notice.
In the pom.xml file the packaging type is 'javascript' and the parent project is 'javascript-project'. The former enables Javascript lifecycle phases and packaging, and which also allows Javascript dependencies which you can also notice in the pom.xml.
There is a profiles.xml file. This defines Sonatype OSS repositories, which is where this plugin and several 'vendor' Javascript libraries are deployed. Releases are eventually synced with Maven Central, but that hasn't happened yet. If you're using Maven 3, you need to copy the profiles to your settings.xml.
The source code to the project lives in src/main/javascript, and the QUnit tests live in src/test/javascript.
When you run 'mvn test' on the command line, all source and test source is copied to a work directory, where all dependencies are also expanded under the lib directory. These can be included by the test suites. After tests are completed, failures are recorded to target/surefire-reports/qunit.txt where they are placed into generated reports exactly as JUnit tests are for Java.
This project does not contain integration tests, but to the best of my knowledge it can easily be done using the Jetty plugin with an integration testing tool of your choice fairly easily. This is a feature I'd like to implement sooner rather than later.
All these tools also work for Webapp projects. I will write a short post about that when I have one working well. To see a sneak peak, check out the hi-og-integration branch of the Soashable OSW project.
This post is lacking on the theory and technical details behind this project, which I've been slower than I'd hoped to deliver. But it's a practical taste of what I've been doing in the past few weeks.