RSS feed
<< Previous | Home

DogmaticMVC: The MVC framework that lets you know when you suck

Yeah, I know, I know.. Does the world really need Yet Another Web Framework?

Ok, perhaps not. But I had this idea, and I felt like implementing it. The result is a web framework that takes test driven development to the extreme.

DogmaticMVC was first presented in a lighting talk at the great Java Posse Roundup conference back in March. The noticeable amount of grinning among the audience encouraged me to submit a talk about it for XP2010. And now I'm presenting it at the Smidig 2010 agile conference in Oslo next week. So I figured it was about time I blogged about it.

Let's see what development with DogmaticMVC looks like. Here's a controller responding to the /HelloWorld URL:


Pretty simple code. (Groovy code actually.) If the client is in the local machine, we output the message "Hello Localhost". Otherwise, we output "Hello world". Accessing the application from localhost should produce "Hello Localhost". Right..? Think again:


DogmaticMVC has intercepted our request, looked at the code, found that it has no tests and refused to let us run it. After all, the the code has no tests, who knows what it will do?

So we add the @TestWith annotation and point it to our test class:


Admittedly not the world's most thorough test, but hey, it executes out code right? Let's see what DogmaticMVC has to say about the matter:


66% coverage? Sure we can do better. We'll add another test that will fake a request from localhost and thus execute line 11:


So now we have 100% line coverage. Very few projects out there in the Real World have that kind of test coverage. So are you happy now, DogmaticMVC? Let's save our test and hit reload:


This is DogmaticMVC letting us know (in polite terms) that even when they cover 100% of our code, our tests really suck. They suck because they don't assert anything about our code. In fact they just execute the code blindly and do not catch that DogmaticMVC mutated our code before running it, carefully injecting bugs by switching less than with greater than etc. Really, what's the use of tests if they don't catch bugs?

We can fix that by adding proper asserts that actually detect that code is not up to spec:


Now what?


This was actually cheating since I added a bug manually just to show that DogmaticMVC will detect it and show you the failing test. Once that "bug" is "fixed", we finally get what we wanted all along: Hello world. (Or as in this case, localhost)


Not only do we have a hello world that seems to work, we have a hello world that we can actually prove will work and that we can trust will continue to work.

As a bonus for reading this long, I present to you: A new feature! Web frameworks is all about features aren't they?

Speaking of features, let us for just a minute pretend that some real customer actually wanted our HelloWorld application. In fact, they like it so much they'd buy if it it only had this extra "near" feature. Sure we can add that? It's just a couple of extra lines of code. They clutter up our class, but the customer really wants it so we end up with this:


Now what does DogmaticMVC have to say about this code?


Here DogmaticMVC no longer sees any reason to stay polite. Feature creep is turning our code into a hairball. But this time we'll pick lazy honesty over hard work Software Craftsmanship and just slap the method with a @ThisMethodSucks annotation:


Are you in Oslo next week? Come see my talk at the Smidig conference, Wednesday 17th.

Introducing lightning talks in your organization


One of my responsibilities at Kantega is to find ways of spreading knowledge within the organization. We have a lot of smart and experienced people in the company. However, our skills and experience is in diverse areas. This is generally a good thing, but it also means we have a lot to learn from each other. The idea came up that if we could get better at sharing, we'll have less reinventing of wheels, we'll do mistakes only once and Kantega will be an even more fun place to work.



At the time this came up, I'd just come back from the Java Posse Roundup 2009 open space conference. The key take away from that conference was: Lightning talks and open space sessions are very efficient (and effective!) ways of sharing knowledge.

A couple months later we were on a company get-together in Barcelona.  Besides consuming a whole lot of tapas and cava and enjoying the city and its architecture, we also set aside half a day to discuss, learn and share about agile software development.  Traditionally, we'd ask one or two "experts" in the company to do a presentation, then split into groups to discuss some questions and join everyone in the end to present the result of each group. This kind of works, but doesn't really engage all the participants.

So with the Java Posse Roundup fresh in mind, I suggested doing something new: One hour of 5-minute lightning talks followed by two hours of open spaces. It was a huge success, so I thought it would be cool to share a few experiences for anyone wanting to do the same:

  • When introducing something new to an organization, do what ever you can to make it a success the first time. It really pays to make an extra effort the first time. People generally will make up their mind after that first experience. You might not  get a second chance.

  • Getting 12 people (out of ~50) to commit to doing a lightning talk on 10 days notice was harder than I thought.
  • I split candidate speakers into three groups: 1: Those who love to talk and do it all the time, 2: those who have a lot of smart things to say but won't unless pushed, and finally 3: those few who will just never stand up in front of a crowd and say anything (unless it's "fire!" :-)

  • I aimed for group 2 with just a few mixed in from group 1. Asking group 1 would be the easy way out: They love talking and my only problem would be to make them shut up after five minutes. But then the concept of lightning talks would have been perceived in the organization as something that is for the people who always talk and that's something I wanted to avoid. Group 3 would be too hard for me, too stressful for them and the resulting talks might not be the best.
  • Almost everyone I asked responded: "..but I am not an Expert on Agile". So I had to convince people I wasn't looking for experts but for people sharing their thoughts and experiences. The notion that you have to be an "expert" to talk about something was well established in our organization and was something we clearly had to "unlearn".

  • Don't just ask people and expect them to show up with a well prepared talk. I followed up on the speakers several times and made sure they were happy with their selected subject and that they were making progress.

  • Three days before Barcelona I joined the speakers in groups of four so they could test-run their talks in front of a small, but real audience. This proved to be immensely useful since it gave people a sense of what five minutes really is and a chance to adjust and improve their presentations. It also made the presenters much more confident on the real presentation.

  • Five minutes works really well because it allows for many points of view in a short time.

  • A count-down timer screen is a must. I placed it so that both the presenter and the audience could see it. With the screen changing from green through yellow to red it's very obvious when you're starting to run out of time. The timer I made wasn't fancy at all, but it served the purpose.

  • Three of twelve talks were intentionally off-topic. Twelve talks on the same subject in a row is a lot. I wanted people to have fun as well. That's key in making something a success the first time.

  • We ran all the presentations from a single computer. Unless you're willing to spend 40% of your time dealing with computer/projector trouble, consider doing the same.

  • Use a good presentation remote (a real RF based, not the flakey bluetooth or wifi ones). People will be less attached to the computer and free to walk around. They'll relax more and look more confident.

  • Remember to take breaks. We did 2x6 lightning talks with a break in between and had breaks before and between the open spaces sessions.

  • Running lighting talks before the open spaces worked really well for getting people to come up with topics for discussion.

  • Some people in management suggested we should prepare some topics in advance. I insisted that's really not what open spaces it about. I must admit I was a little worried though. Open spaces was new to most people and unlike the Java Posse Roundup, this wasn't a self-selecting group of open space enthusiasts.  Someone also suggested we wrote summaries of the discussions, but I refused. Whatever happens happens and when it's done it's done etc.

  • Turns out I had no reason to worry. We had 30% more suggestions that we had room for.

  • The feedback afterwards was very good. I was saw people I'd never seen present before give excellent talks.
Do you have experience introducing introducing lightning talks, open spaces or other kinds of knowledge sharing in your organization?  I'd love to hear your thoughts!

Make your war file executable with the Jetty Console Maven plugin

A while back I made a little Maven plugin that takes a war file and makes it executable. With executable I mean that it embeds a Jetty servlet container. Running java -jar myapp.war will deploy your war with the embedded Jetty instance.

This provides a very convenient distribution method for Java web applications. It lets you distribute your application as a single artifact. Your users are no longer forced to install a big and ugly app server just to run your app.

But if they really want to, the war is still a war file that can be deployed the "normal" way in Tomcat, Glassfish, Weblogic, Websphere or any servlet compliant web server. (You tell me you actually use Websphere? Seriously!?).

With a single distribution in a single file, there's also less chance of your users getting confused about how to get your application running.

Jan Bartel of Jetty fame asked for a link describing this plugin and since I didn't really have any thing useful, here's a blog post:

An example: The Puffin Secrets Webapp

Meet the Puffin Secrets webapp. This very small, yet very useful web application let us listen in on the puffins while they chat about Jetty:


Since puffins are a bit shy, we need to click the button to see what they really think about Jetty:


To make this war file executable, we need to add a bit of plugin configuration to our Maven pom.xml:

<plugin>
<groupId>org.simplericity.jettyconsole</groupId>
<artifactId>jetty-console-maven-plugin</artifactId>
<version>1.23</version>
<executions>
<execution>
<goals>
<goal>createconsole</goal>
</goals>
</execution>
</executions>
</plugin>

After running mvn clean install, we should now have a target directory looking like this:


Notice the -jetty-console.war version of your war file. This war file is now runnable with java -jar (On a Mac it's actually double-clickable!). Running the war will start a little Swing console (unless run on a server):


The flies are there to remind you that you probably have bugs in your code. Still you might want to use a less generic background image. This can be done by adding the following configuration:


<plugin>
<groupId>org.simplericity.jettyconsole</groupId>
<artifactId>jetty-console-maven-plugin</artifactId>
<version>1.23</version>
<executions>
<execution>
<goals>
<goal>createconsole</goal>
</goals>
<configuration>
<backgroundImage>${basedir}/src/main/jettyconsole/puffin.jpg</backgroundImage>
</configuration>
</execution>
</executions>
</plugin>


This gives us a much more puffin-relevant background:


The console is currently pretty simple. It allows the user to select a port and start the application. As a convenience the console will open a browser with the correct URL. This saves the user some seconds. (When demoing a product, seconds matter!)

Command line options

While the graphical console is nice for demoing an application or distributing it to testers, for installation on a server we need some command line interaction. You can see a list of available options by typing java -jar myapp.war --help

Usage: java org.simplericity.jettyconsole.JettyConsoleStarter [--option=value] [--option=value]

Options:
--sslProxied - Running behind an SSL proxy
--port n - Create an HTTP listener on port n (default 8080)
--bindAddress addr - Accept connections only on address addr (default: accept on any address)
--forwarded - Set reverse proxy handling using X-Forwarded-For headers
--contextPath /path - Set context path (default: /)
--headless - Don't open graphical console, even if available
--help - Print this help message
--tmpDir /path - Temporary directory, default is /tmp

Plugins

The core of the Jetty console is intentionally kept as small as possible. Additional functionality can be included by adding plugins to your plugin configuration. You might want to add the log4j plugin:

<configuration>
<backgroundImage>${basedir}/src/main/jettyconsole/puffin.jpg</backgroundImage>
<additionalDependencies>
<additionalDependency>
<artifactId>jetty-console-log4j-plugin</artifactId>
</additionalDependency>

</additionalDependencies>
</configuration>

This should give you an extra option when running --help :

Usage: java org.simplericity.jettyconsole.JettyConsoleStarter [--option=value] [--option=value]

Options:
--sslProxied - Running behind an SSL proxy
--port n - Create an HTTP listener on port n (default 8080)
--bindAddress addr - Accept connections only on address addr (default: accept on any address)
--forwarded - Set reverse proxy handling using X-Forwarded-For headers
--contextPath /path - Set context path (default: /)
--headless - Don't open graphical console, even if available
--help - Print this help message
--tmpDir /path - Temporary directory, default is /tmp
--logConfig file - Read log4j configuration from file

The other plugins currently available are:

ajp: Lets you configure an AJP connector in Jetty
requestlog: Allows you to log requests to an access log for traffic analysis
jsp: Adds JSP support to your application
jettyxml: Allows you to apply arbitrary Jetty XML configurations to your Server or WebAppContext
gzip: Compresses your HTML, CSS and Javascript for bandwidth savings

If the available plugins don't match your needs, it's quite easy to make your own and include it with in <additionalDependencies/>. <additionalDependencies/> can also be used to add normal Maven dependencies, such as a database driver referred to in jetty.xml

Maven repository configuration

Since this plugin is not (yet) in the Maven Central repository, you'll need to add a pluginRepository to your pom.xml:

<pluginRepositories>
<pluginRepository>
<id>kos</id>
<url>http://opensource.kantega.no/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>

<repositories>
<repository>
<id>kos</id>
<url>http://opensource.kantega.no/nexus/content/groups/public/</url>
</repository>
</repositories>

The complete puffin example webapp is available in Subversion here:

http://simplericity.org/svn/simplericity/trunk/jetty-console-example/