I’ve had an opportunity recently to work on a product that needed an RIA web interface, and I chose my recent favorite tool for this, Vaadin. The services for this project needed to be highly scalable, and lent themselves well to functional techniques, so I selected Scala as my language of choice. I build my projects with Maven, for reasons I won’t go into right now, and I do much of my JVM-language work in Intellij’s excellent IDEA IDE.
Given these tools, I found a way to facilitate very rapid development of web UI’s, and I thought I’d pass it along.
Another technique I use, which I’ll expound on later, is creating “dummy” implementations of all of my backing services for my application. The “real” implementations are written as OSGi services, in separate modules from my UI. The UI is packaged as a war, but is also OSGi aware, with a bundle activator. This activator only gets called if the war is deployed into an OSGi container, and not otherwise. This allows the app to select which implementation of the services it uses – the “dummy” ones when it’s deployed outside of OSGi, and the “real” ones when they’re available.
This means I can use the handy Maven jetty plugin to quickly spin up my application and test it on my local workstation, without needing all of the dependencies (like a data store and such) of my real services. That’s good, in that I can get my “cycle time” down to a few seconds, where “cycle time” is the time between making a change and actually being able to test it in my browser.
We can do better, though.
I’m using Scala as my language of choice for building the UI as well, as it works just fine with Vaadin (and with everything else in the JVM ecosystem, for that matter, which is why I didn’t choose a non-JVM language – but that’s yet another rant).
I compile my Scala with the Maven scala plugin – here’s where the next handy bit comes into play. Turns out the Scala plugin has a goal called “cc”, for continuous compilation. Using this, I can fire up Maven with a “mvn scala:cc” command, and leave it running. Then I also use the “mvn jetty:run” command in another window to fire up the web application, and leave it running as well.
Here’s my configuration for the Scala plugin:
org.scala-tools maven-scala-plugin 2.9.1 compile testCompile ${scala.version} -target:jvm-1.5
And for Jetty:
org.mortbay.jetty maven-jetty-plugin 6.1.9 10 src/main/webapp jetty.xml file realm.properties stop 8889
Now I go back to my IntelliJ and start coding. Every time IntelliJ saves (which it does automatically unless you tell it not to), the Scala plugin compiles the files. This generates a new .class file, which the Jetty plugin (well, technically, Jetty itself) detects, and in response, reloads the running classes for the web application.
Net effect is that I can make my change and by the time I switch back to the browser, my new code is running. I test my change, emit the appropriate profanity, and go back to editing, all within a second or two.
This has profound effects on how you develop a UI, which every dynamic language aficionado knows (e.g. like Ruby/Rails or Python/Django). You don’t hesitate to experiment, and you get to see the visual effect of your changes right away. The good news is that I get to do this with my language of choice, and with all the power of the JVM ecosystem to support it.
The technique is not perfect – I’ve found that if you edit some resources or webapp files (images and such), it’s possible the Jetty plugin doesn’t “see” the change. Of course, two things help with that considerably: first, it’s lightning-fast to just Control-C the jetty plugin task and re-launch it, and second a Vaadin app generally doesn’t use many resources, unlike JSP or many other frameworks that make extensive use of templates.
Once in a while I’ve found the scala:cc task will report that it’s lost it’s connection to the “fsc” (fast scala compiler) background process – again, quickly control-c-ing the task and starting it again solves the problem every time.
Overall, I can crank UI out pretty darn quick with this method, and given that I can TDD even my UI code using Vaadin, I find the overall combination very effective and efficient.
Apache’s ServiceMix 4 is a unique combination of OSGi container and JBI-compliant ESB, but in addition to this it’s also a capable web application container. More specifically, it can contain a webapp container, but the effect is the same…
My current favorite tool for cranking out MVC-style webapps is the Lift framework, so I thought I’d document here the process for deploying a Lift webapp into ServiceMix 4.
The good news is that it’s very straightforward.
First, build the .war for your Lift app using mvn package. This will result in a .war file in the target directory of your project, and is well-covered by the Lift documentation if you need more details. In my case, I started with a slightly modified version of the PocketChange example app for Lift.
Now start servicemix with
bin/servicemix
Done from the root directory of your ServiceMix install. You should see the ServiceMix banner after a few moments, followed by a prompt.
In the console, type the “osgi” command to enter OSGi mode. then
install war:file:///tmp/admin-0.1.war?Webapp-Context=admin
You’ll see some startup messages as your webapp is digested by ServiceMix, turned automagically into a bundle, and processed by various intestinal organs such as the HTTP service.
Now surf to
http://localhost:8080/admin/
And up comes your application!!
I recently had the chance to dive into a new project, this one with a rich web interface. In order to create acceptance test around the (large and mostly untested) existing code, we’ve started writing specs acceptance tests.
Once we have our specs written to express what the existing functionality is, we can refactor and work on the codebase in more safety, our tests acting as a “motion detector” to let us know if we’ve broken something, while we write more detailed low-level tests (unit tests) to allow easier refactoring of smaller pieces of the application.
What’s interesting about our latest batch of specs is that they are written to express behaviours as experienced through a web browser – e.g. “when a user goes to this link and clicks this button on the page, he sees something happen”. In order to make this work we’ve paired up specs with Selenium, a well-known web testing framework.
By abstracting out the connection to Selenium into a parent Scala object, we can build a DSL-ish testing language that lets us say things like this:
object AUserChangesLanguages extends BaseSpecification { "a public user who visits the site" should beAbleTo { "Change their language to French" in { open("/") select("languageSelect", "value=fr") waitForPage location must include("/fr/") } "Change their language to German" in { select("languageSelect", "value=de") waitForPage location must include("/de/") } "Change their language to Polish" in { select("languageSelect", "value=pl") waitForPage location must include("/pl/") } } }
This code simply expresses that as a user selects a language from a drop-down of languages, the page should refresh (via some Javascript on the page) and redirect them to a new URL. The new URL contains the language code, so we can tell we’ve arrived at the right page by the “location must include…” line.
Simple and expressive, these tests can be run with any of your choice of browsers (e.g. Firefox, Safari, or, if you insist, Internet Explorer).
Of course, there’s lots more to testing web pages, and we’re fleshing out our DSL day by day as it needs to express more sophisticated interactions with the application.
We can get elements of the page (via Xpath), make assertions about their values, click on things, type things into fields and submit forms, basically all the operations a user might want to do with a web application.
There are some frustrations, of course. The Xpath implementation on different browsers works a bit differently – well, ok, to be fair, it works on all browsers except Internet Exploder, where it fails in various frustrating ways. We’re working on ways to overcome this that don’t involve having any “if browser == ” kind of logic.
It’s also necessary to start the Selenium RC server before running the specs, but a bit of Ant magic fixes this.
We’ve got these specs running on our TeamCity continuous integration server, using the TeamCity runner supplied with Specs, where we get nicely formatted reports as to what’s pending (e.g. not finished being written yet), what’s passing, and what’s failing.
The specs written with Selenium this way are also a bit slow, as they must actually wait in some cases for the browser (and the underlying app!) to catch up. When run with IE as the browser, they’re more than just a bit slow, in fact…
They are, however, gratifyingly black-box, as they don’t have any connection to the code of the running application at all. For that matter, the application under test can be written in any language at all, and in this case is a combination of J2EE/JSP and some .NET.
There’s a lot of promise in this type of testing, even with it’s occasional frustrations and limitations, and I suspect we’ll be doing a lot more of it.
While the powerful Spring Framework is commonly used for Java web applications, there no reason you can’t also use it for good old-fashioned command-line apps as well.
I recently had occasion to take a large web application and attempt to break a bit out of it to run as a standalone jar, and made a few interesting discoveries along the way.
Let’s say you want to run the following main method:
package com.point2; import com.point2.MyBeanClass; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyMainClass { public static void main(String args[]) { try { MyBeanClass myClass = getMyBean("beanId"); myClass.doImportantWork(); } catch (Exception e) { e.printStackTrace(); } } private static MyBeanClass getMyBean(String beanId) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-beans.xml"); return (MyBeanClass) applicationContext.getBean(beanId); } }
This class simply creates the Spring application context, gets a bean, and executes the doImportantWork method on it. As it’s a main method, we can call it from the command-line, with no container or deployment required, if we could put our webapp into an executable jar, along with all it’s dependencies (which include Spring).
As I was lucky enough to have a Maven project for my webapp, my first thought was to use the Maven “assembly” plugin to create a single jar file with all required classes. This worked fine, creating my webapp-1.0-jar-with-dependencies.jar as advertised. The problem came when I tried to run my command-line app. I created a little script like so:
java -cp target/webapp-1.0-jar-with-dependencies.jar com.point2.MyMainClass
And executed it. Immediately Spring complained about not being able to find NamespaceHandlers for some obscure namespace I used in my Spring configuration files.
Hmph.
After a long dig through the relevant doc, it turns out that several of the Spring jar files have a file called “spring.schemas” in their META-INF directories, and a corresponding file called “spring.handlers” that says where to get the appropriate handlers for the schemas they understand. Unfortunately, the files are not the same in all of the various Spring dependency jars – in other words, the schemas and handlers in one Spring jar are different from the schemas and handlers in another.
When the assembly plugin puts all these jars together into one uber-jar, the “last man in wins”, in other words, whatever Spring jar is processed last has it’s spring.schema and spring.handlers file end up in the uber-jar, overwriting the others.
This results in Spring not being able to find the proper list of handlers on startup, hence my kaboom.
There’s an open bug discussing this problem in the Jira for the assembly plugin, but fortunately there’s another option: The maven “shade” plugin.
Add the following plugin magic to your POM’s build section:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
The “AppendingTransformer” bit is where we tell the plugin to concatenate together all resources with the same name, instead of just using the most recent one encountered.
Then change the element in your project’s POM to say “jar” instead of “war”, and do a
mvn package
Now you end up with a jar file called “webapp-1.0.jar” instead of the war file in your target directory, but this time with all the proper spring.schema and spring.handler files appended together.
Now you can say
java -cp target/webapp-1.0.jar com.point2.MyMainClass
And Spring happily winds up an application context and works as expected.
Happy jar-ing!