Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.
You searched this site for "play". 218 entries found.

You can also try this same search on Google.

Integrating HTML5 Boilerplate with Scalate and Play

HTML5 Boilerplate is a project that provides a number of basic files to help you build an HTML5 application. At its core, it's an HTML template that puts CSS at the top, JavaScript at the bottom, installs Chrome Frame for IE6 users and leverages Modernizr for legacy browser support. It also includes jQuery with the download. One of the major benefits of HTML5 Boilerplate is it ships with a build system (powered by Ant) that concatenates and minimizes CSS and JS for maximum performance. From html5boilerplate.com:

Boilerplate is not a framework, nor does it prescribe any philosophy of development, it's just got some tricks to get your project off the ground quickly and right-footed.

I like the idea of its build system to minify and gzip, but I'd probably only use it if I was working on a project that uses Ant. Since I'm using it in a Play project, the whole Ant build system doesn't help me. Besides, I prefer something like wro4j. Wro4j allows you to specify a group of files and then it compiles, minimizes and gzips them all on-the-fly. As far as I know, Play doesn't have any support for Servlet Filters, so using wro4j in Play is not trivial.

The good news is Play has a GreenScript module that contains much of the wro4j functionality. However, since I'm using Scalate in my project, this goodness is unavailable to me. In the future, the Scalate Team is considering adding better wro4j, JavaScript and CSS integration. In the meantime, I'm going to pretend I don't care about concatenation and minimization and trundle along without this feature.

To add HTML5 Boilerplate to my Play project, I performed the following steps:

  • Downloaded the 2.0 Zipball.
  • Copied all the static files to my project. Below are the commands I used (where $boilerplate-download is the expanded download directory and ~/dev/play-more is my project):
    cd $boilerplate-download
    cp 404.html ~/dev/play-more/app/views/errors/404.html
    cp *.png ~/dev/play-more/public/.
    cp crossdomain.xml ~/dev/play-more/public/.
    cp -r css ~/dev/play-more/public/stylesheets/.
    cp favicon.ico ~/dev/play-more/public/.
    cp humans.txt ~/dev/play-more/public/.
    cp -r js/libs ~/dev/play-more/public/javascripts/.
    cp robots.txt ~/dev/play-more/public/.
    
  • Copied the index.html to ~/dev/play-more/app/templates/layouts/default.jade and modified it to use Jade syntax. Since I downloaded the comments-heavy version, I modified many of them to be hidden in the final output.
    -@ val body: String 
    -@ var title: String = "Play More"
    -@ var header: String = ""
    -@ var footer: String = ""
    !!! 5
    / paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ 
    <!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
    <!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
    <!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
    -# Consider adding an manifest.appcache: h5bp.com/d/Offline 
    <!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
    head
      meta(charset="utf-8")
    
      -# Use the .htaccess and remove these lines to avoid edge case issues. More info: h5bp.com/b/378 
      meta(http-equiv="X-UA-Compatible" content="IE=edge,chrome=1")
    
      title=title
      meta(name="description" content="")
      meta(name="author" content="Matt Raible ~ [email protected]")
    
      -# Mobile viewport optimized: j.mp/bplateviewport 
      meta(name="viewport" content="width=device-width,initial-scale=1")
    
      -# Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons
    
      -# CSS: implied media=all
      link(rel="stylesheet" href={uri("/public/stylesheets/style.css")})
      -# end CSS
    
      -# More ideas for your <head> here: h5bp.com/d/head-Tips 
      -#
        All JavaScript at the bottom, except for Modernizr / Respond.
        Modernizr enables HTML5 elements & feature detects; Respond is a polyfill for min/max-width CSS3 Media Queries
        For optimal performance, use a custom Modernizr build: www.modernizr.com/download/ 
    
      script(type="text/javascript" src={uri("/public/javascripts/libs/modernizr-2.0.6.min.js")})
    body
      #container
        header = header
        #main(role="main")
          != body
        footer = footer
    
      -# JavaScript at the bottom for fast page loading 
      
      / Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline 
      script(type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js")
      :javascript
        window.jQuery || document.write('<script src={uri("/public/javascripts/libs/jquery-1.6.2.min.js")}><\/script>')
    
      -# Change UA-XXXXX-X to be your site's ID 
      :javascript
        window._gaq = [['_setAccount','UA-25859875-1'],['_trackPageview'],['_trackPageLoadTime']];
        Modernizr.load({
          load: ('https:' == location.protocol ? '//ssl' : '//www') + '.google-analytics.com/ga.js'
        });
    
      -# Prompt IE 6 users to install Chrome Frame. Remove this if you want to support IE 6. 
      -# http://chromium.org/developers/how-tos/chrome-frame-getting-started 
      /[if lt IE 7]
        script(src="//ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js")
        :javascript
          window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})
            
    != "</html>"
    
  • Next, I had to add support for layouts to my homegrown Scalate support. I did this by specifying a layoutStrategy when initializing the TemplateEngine. From play-more/app/controllers/ScalateTemplate.scala:
    engine.classLoader = Play.classloader
    engine.layoutStrategy = new DefaultLayoutStrategy(engine, 
      Play.getFile("/app/templates/layouts/default" + scalateType).getAbsolutePath)
    engine
    

That's it! Now I have HTML5 Boilerplate integrated into my Play/Scalate/Jade application. To set the title and header in my index.jade, I simply added the following lines at the top:

- attributes("title") = "Counting"
- attributes("header") = "HTML5 Rocks!"

CoffeeScript Tip
Yesterday, I mentioned that I was having issues getting CoffeeScript to work with Scalate and that I was going to try and get the in-browser compiler working. First of all, reverting to Scalate 1.4.1 didn't work because there is no CoffeeScript support in 1.4.1. So I stayed with 1.5.2 and used PandaWood's Running CoffeeScript In-Browser Tutorial. I copied coffee-script.js to ~/dev/play-more/public/javascripts/libs and added a reference to it in my default.jade layout:

-# JavaScript at the bottom for fast page loading 
script(type="text/javascript" src={uri("/public/javascripts/libs/coffee-script.js")})

Then I was able to write CoffeeScript in a .jade template using the following syntax:

:plain
  <script type="text/coffeescript">
    alert "hello world"
  </script>

Summary
If you've integrated HTML5 Boilerplate into your Play application, I'd love to hear about it. Now that I have all the infrastructure in place (Jade, CoffeeScript, HTML5 Boilerplate), I'm looking forward to getting some development done. Who knows, maybe I'll even come up with my own Play Un-Features That Really Irk My Inner Geek.

Posted in Java at Sep 28 2011, 08:49:35 AM MDT 2 Comments

Trying to make CoffeeScript work with Scalate and Play

A few weeks ago, I wrote about integrating Scalate with Play.

The next steps in my Play Scala adventure will be trying to get the CoffeeScript module to work. I also hope to integrate HTML5 Boilerplate with Jade and Scalate Layouts.

Since my last writing, the Scalate Team has created a new branch for Scala 2.8.x (that's compatible with Play) and released 1.5.2. To upgrade my Play application to use this version, I changed my dependencies.yml to have the following:

  - org.fusesource.scalate -> scalate-core 1.5.2-scala_2.8.1:
      transitive: false
  - org.fusesource.scalate -> scalate-util 1.5.2-scala_2.8.1:
      transitive: false

Unfortunately, this release breaks Scalate's CoffeeScript support because it wraps the code with illegal comments. This has been fixed in the latest snapshot, but no new release has been cut. However, even if it did work, it's not quite what I'm looking for. The 1.5.2 release allows for compiling inline CoffeeScript on-the-fly, but I'd rather store my .coffee files external to the page.

To try and figure out how to do this, I sent a message to the Scalate Google Group asking Does Scalate allow for referencing (and compiling) CoffeeScript files like the plugin for Play? My email prompted the Scalate Team to do some modifications that seemed to do exactly what I was looking for.

FWIW I've just checked in a couple of coffeescript examples. To run it, grab the code & do a local build...

http://scalate.fusesource.org/source.html
http://scalate.fusesource.org/building.html

then run this...
cd samples/scalate-example 
mvn jetty:run
then open http://localhost:8080/coffee/index

there are 2 sample jade files which use embedded coffee or a separate coffee file (using the .js extension in the <script src attribute>

https://github.com/scalate/scalate/tree/master/samples/scalate-exampl...

e.g. here's a jade file references a separate .js file for a coffee script which gets converted to .js on the server...

https://github.com/scalate/scalate/blob/master/samples/scalate-exampl...

To try out the improved CoffeeScript support, I checked out the source and fumbled with Git branches for a bit before I got latest version of Scalate to build. Unfortunately, it didn't work because Play doesn't know how to process the .js and .css files.

@67o8fflce 
Application.foo.js action not found 
Action not found 
Action Application.foo.js could not be found. Error raised is 
Controller controllers.Application.foo not found 
play.exceptions.ActionNotFoundException: Action Application.foo.js not 
found 
        at play.mvc.ActionInvoker.getActionMethod(ActionInvoker.java: 
588) 
        at play.mvc.ActionInvoker.resolve(ActionInvoker.java:85) 
        at Invocation.HTTP Request(Play!) 
Caused by: java.lang.Exception: Controller controllers.Application.foo 
not found 
        ... 3 more 
08:20:21,133 ERROR ~

Based on this error, I assumed I needed a Controller to do receive the .js and .css requests and compile them accordingly with Scalate. I changed my Jade template to have the following:

script(src="/assets/foo.js" type="text/javascript") 

Then I added a new route to my Play application:

  GET     /                           Application.index
  GET     /assets/{template}          ScalateResource.process

My ScalateResource.scala class is as follows:

package controllers 

import play.mvc._ 

object ScalateResource extends Controller { 

  def process(args: (Symbol, Any)*) = { 
    var template = params.get("template") 
    // replace .js with .coffee 
    template = template.replace(".js", ".coffee") 
    // replace .css with .scss 
    template = template.replace(".css", ".scss") 
    ScalateTemplate(template).render(); 
  } 
} 

Unfortunately, when I tried to access http://localhost:9000/assets/foo.js, I received the following error:

TemplateException occured : Not a template file extension (md | markdown | ssp | scaml | mustache | jade), you requested: coffee

At this point, I still haven't figured out how to solve this. I can only assume that the reason this works in the example application is because it uses a TemplateEngineFilter that's mapped to /*.

As I see it, I have a few choices if I want to continue using CoffeeScript and Scalate in my application:

  1. Revert to an older build of Scalate that uses the in-browser CoffeeScript compiler.
  2. Try to get a new version released that fixes the comment bug and use inline CoffeeScript.
  3. Keep trying to figure out how to get external files compiled by Scalate.

Obviously, I'd like to do #3 the most, but with the lack of responses from the Scalate group, this seems like the most challenging. Since #1 is the easiest (and I can complete without anyone's help), I'll be going that route for now. With any luck, the 2nd and third solutions will surface as options before my talk in November.

Update Oct 4, 2011: I was able to get external CoffeeScript files working! It was rather simple actually. I just tried the Play CoffeeScript module again, using Scalate's {uri("/path")} helper. For example, in a Jade template:

script(type="text/javascript" src={uri("/public/javascripts/script.coffee")})

This compiles the CoffeeScript file on the server and returns JavaScript. Sweet!

Posted in Java at Sep 27 2011, 01:59:18 PM MDT 3 Comments

Integrating Scalate and Jade with Play 1.2.3

At the beginning of this year, I decided I wanted to learn Scala. Since I'm a Web Frameworks Aficionado, I figured the best way to do that would be to learn Lift. I entered these two items on my todo list and let them lie for a couple months. After attending TSSJS 2011 and having a conversation with James Strachan, I added a couple more technologies to my learning list. James had great things to say about both CoffeeScript and Jade and I decided to learn those as well.

In May, Devoxx announced their Call For Papers and I started reminiscing about how awesome last year's trip was. I decided I'd try to get accepted again and started brainstorming about talks I'd like to give. I came up with "Comparing Scala Web Frameworks" and "HTML5 with Play Scala, CoffeeScript and Jade". The reason I chose Play over Lift for the latter talk is because I think it fits a lot more with the MVC mindset I have and the easy-to-learn nature of web frameworks I enjoy using. Both topics sounded very interesting to me, and I figured they'd also inspire me to learn the technologies in a brute-force fashion; where I was under a time constraint and would be embarrassed in front of a large audience if I didn't succeed.

In mid-July, I got an email from Stephan inviting me to speak again at the 10th edition of Devoxx. I smile splashed across my face and I quickly realized I had a lot to learn. Since I was still in vacation mode after summer vacation in Montana, I decided to wait until I returned from Cape Cod to start studying. While on my 2nd summer vacation, I received an email from Devoxx stating that they'd like me present "HTML5 with Play/Scala, CoffeeScript and Jade".

To learn all these technologies, I decided on an In Anger approach - where I would study minimally and learn mostly by doing. I ordered CoffeeScript on August 8th and Programming in Scala, 2nd Edition the following week (August 17th). I started reading both books while traveling the following week (I found CoffeeScript and Scala to be very similar, so I don't know if I'd recommend learning them at the same time). That same week, I started integrating Scalate (Jade) into a new Play Scala application.

Scalate advertises on their homepage that it works with Play via the play-scalate module. They neglect to mention that this module hasn't been updated in over a year or what version of Play it works with. I tried to use the scalate-0.7.2 version and quickly ran into issues. I posted a message to the Scalate Google Group explaining my compilation issues and stacktraces. The response? Crickets.

Next, I tried posting to the Play Google Group and got a much better response. Here's what they said:

Looking at the Scalate module code, I don't think it can work as is with Play Scala 0.9.1. The latest version is more than 1 year old, and we have made a lot of changes in the API.
...
The integration of Scalate is pretty difficult if you plan to get the same kind of experience than the native Play scala template regarding auto-reload and error reports.

You can try to port the module to 0.9.1, basically all it has to do is to provide a plugin that detect changes to scaml file, and recompile them. No special integration with the Play API is needed.

After learning that play-scalate was out-of-date, I contacted the project owner via GitHub and tried to get everything working with Play 1.2.3 and Scalate 1.5.1. I updated the dependencies in the project, fixed compilation issues and tried to build. No dice:

build: 
    [mkdir] Created dir: /Users/mraible/dev/play-scalate/tmp/classes 
   [scalac] Compiling 7 source files to /Users/mraible/dev/play-scalate/tmp/classes 
   [scalac] error: class file needed by Binding is missing. 
   [scalac] reference type Serializable of package scala refers to nonexisting symbol. 
   [scalac] one error found

I posted this error to the Play Group, discovered it was caused by Scalate 1.5.1 requiring Scala 2.9. I downgraded to Scalate 2.4.1 and got another nice cryptic error:

build: 
    [mkdir] Created dir: /Users/mraible/dev/play-scalate/tmp/classes 
   [scalac] Compiling 7 source files to /Users/mraible/dev/play-scalate/tmp/classes 
   [scalac] error: class file needed by ScalaController is missing. 
   [scalac] reference value dispatch of package <root> refers to nonexisting symbol. 
   [scalac] one error found

Apparently, this was caused by another Scala versioning issue and I was offered a much simpler solution for integrating Scalate. Below are the steps I performed to integrate Scalate 1.4.1 with Play 1.2.3.

  1. Updated dependencies.yml to references Scala and Scalate dependencies.
    require:
        - play
        - play -> scala 0.9.1
        - org.fusesource.scalate -> scalate-core 1.4.1:
            transitive: false
        - org.fusesource.scalate -> scalate-util 1.4.1:
            transitive: false
    
  2. Added Scalate configuration elements to application.conf.
    scalate=jade
    jvm.memory=-Xmx256M
    
  3. Created a ScalateTemplate class to contain the Scalate Engine and render the template.
    package controllers
    
    import play.Play
    
    object ScalateTemplate {
    
      import org.fusesource.scalate._
      import org.fusesource.scalate.util._
    
      lazy val scalateEngine = {
        val engine = new TemplateEngine
        engine.resourceLoader = new FileResourceLoader(Some(Play.getFile("/app/views")))
        engine.classpath = Play.getFile("/tmp/classes").getAbsolutePath
        engine.workingDirectory = Play.getFile("tmp")
        engine.combinedClassPath = true
        engine.classLoader = Play.classloader
        engine
      }
    
      case class Template(name: String) {
        val scalateType = "." + Play.configuration.get("scalate");
    
        def render(args: (Symbol, Any)*) = {
          scalateEngine.layout(name + scalateType, args.map {
            case (k, v) => k.name -> v
          } toMap)
        }
      }
    
      def apply(template: String) = Template(template)
    }
    
  4. Created a Scalate trait to override the render() method in Play's Controller class.
    package controllers
    
    import play.mvc.Http
    
    trait Scalate {
    
      def render(args: (Symbol, Any)*) = {
        def defaultTemplate = Http.Request.current().action.replace(".", "/")
        ScalateTemplate(defaultTemplate).render(args: _*);
      }
    }
    
  5. Created an Application.scala controller with a default index method.
    package controllers
    
    import play.mvc._
    import models._
    
    object Application extends Controller with Scalate {
    
      def index = {
        render('user -> User("Raible"))
      }
    }
    
    The models/User.scala class is very simple:
    package models
    
    case class User(name:String)
    
  6. Lastly, I created an index.jade file in views/Application.
    -@ var user: models.User
    p Hi #{user.name},
    - for(i <- 1 to 3)
      p= i
    p See, I can count!
    

After getting all this working, I decided it was time to get it into production. As luck would have it, Heroku had just announced Play support a few days earlier. I heard through the grapevine that Play Scala would work, so I gave it a try. It was amazingly easy. All I had to do was create an account, create a "Procfile" in my application's root directory and run a heroku command followed by a git push. It all looked great until Play tried to compile my Jade templates as Groovy templates:

Cannot start in PROD mode with errors 
Template compilation error (In /app/views/Application/index.jade around line 2) 
The template /app/views/Application/index.jade does not compile : #{user.name} is not closed. 
play.exceptions.TemplateCompilationException: #{user.name} is not closed. 
       at play.templates.TemplateCompiler.generate(TemplateCompiler.java:102) 
       at play.templates.TemplateCompiler.compile(TemplateCompiler.java:15) 
       at play.templates.GroovyTemplateCompiler.compile(GroovyTemplateCompiler.java:4 1)

The solution from Guillaume was simple enough and I renamed my "views" directory to "templates" and updated ScalateTemplate.scala accordingly. You can see the deployed application at http://play-more.herokuapp.com.

The next steps in my Play Scala adventure will be trying to get the CoffeeScript module to work. I also hope to integrate HTML5 Boilerplate with Jade and Scalate Layouts. I'll be doing this with the mindset that HTML and JavaScript aren't that bad. I expect a lot from CoffeeScript and Jade and hope I enjoy them as much as Strachan. ;-)

In the meantime, here's some interesting links I've seen recently encountered that discuss Scala and/or Play. I dig the passion and activity that exists in these communities.

Posted in Java at Sep 07 2011, 01:21:41 PM MDT 10 Comments

Oregon, Cape Cod and Fun in Winter Park

Silver Falls State Park I'm proud to say it's been almost a month since my last blog entry. This can only mean one thing → I've been having too much fun to blog. The good news is I finally found time to write about our recent adventures, so grab yourself a tasty beverage and read on.

Within hours of my last blog post, Trish and I hopped on a plane to visit my good friends, Clint and Autumn, in Oregon. We flew into Portland and spent the weekend hiking in Silver Falls and drinking good beer at the Oregon Brewers Festival and Edgefield. Edgefield is one my favorite places on Earth, encapsulating a farm/resort environment with 27 different features. The features range from a soaking pool to a winery to a pool hall to scotch tasting in a shack next to a garden.

Thirsty Field of Flowers

The weekend was especially fun since Autumn was pregnant and it was two weeks before the due date of their first child. Broderick Jordan Wilburn Foster was born yesterday and I hear the whole family is doing well.

Trish and I spent the night at Edgefield on Saturday and caught an early flight from Portland to Boston the next morning. Her brother (also named Matt) lives near Boston and we drove our rental Volvo convertible (to fit in with the New Englanders) to his house Sunday night. On the Hertz Bus from the airport met Nigel Parry, a professional photographer. Not just anybody, but someone that's shot pictures of some very famous people. Trish is also a photographer, so they had a long conversation and it inspired her to resign from her sales job last week. Actually, it wasn't that meeting, she's been wanting to be a famous photographer since she was in high school. Now that dream shall happen. She's awesome.

On Monday afternoon, we picked up Abbie and Jack from the Boston airport. They flew up from West Palm Beach on their first unaccompanied minors flight. We drove them to Cape Cod and settled into Trish's parents house near the water. The rest of the week, we had a blast with our friends Chris and Julie and the entire McGinity clan. We boated, grilled, flew down the water slides, played miniature golf and toured Martha's Vineyard. We had a pool party, played some pool and sang our hearts out at karaoke. Trish's brother's kids are the same age as mine, so you couldn't wipe the smiles off our kids' faces, especially when we had the tunes cranked with the top down on the convertible.

Wheeee!! Hercules! Michael and Jack

Monkey Shadows

For more pictures of this super-fun trip, see Summer Fun in Oregon and Cape Cod part 1 and 2.

After returning from Boston, we had a week without kids and lived it to the fullest with a John Butler Trio concert at Red Rocks and the Winter Park Beer Festival. Trish's friend Joanna and my good friend, "The Professor" joined us for a weekend of mountain biking and sweet mountain views. We even got to hang out with James Ward and his wife Jenny at the beer festival. Sunday, we hiked up the beautiful Columbine Lake Trail. Trish's dog, Sagan (named after Carl) chased sticks and was his crazy self as usual.

Cheers! Crazy Sagan!

We drove back Monday morning to be there for the kids first day of school. They sure start early these days don't they?

First Day of 2nd and 3rd Grade

I rode my bike 168 miles to and from work throughout the following week. The next weekend, we took the kids up to the Ski Shack for their first time. I hired a guy to make queen-size bunk beds for them, so they had a blast in their new roomy beds. On Saturday, we had a garage sale since the previous owners left a bunch of beds and couches and we didn't need all that furniture. The turnout was great and we got to hang out with Jodi and James, Suzie, and The Lamonts. All of these folks are old friends that just happened to be in the mountains for the weekend. One of Trish's best friends, Chris, has a place less than a mile from us and we had a blast with her on Saturday night. Thanks for the fun memories Chris!

On Sunday, we took the kids the Winter Park Base Area where they have Disneyland in the Mountains as I like to call it. An alpine slide, miniature golf, a maze, a climbing wall and a Chili Cook-Off to keep Daddy happy. We met our good friend Suzie there and had a lot of fun with Chris, Brice and their crazy kids. Enjoying an Avery White Rascal at the Cheeky Monk's happy hour was the perfect way to end the day.

Abbie and Jack on the Cabriolet Chili Cook Off! Abbie on the Trampoline

Nice flip Jack!

Sunday night, we were graced with the presence of a beautiful sunset.

Sunset Views from the shack

Happy Kids Sunday Sunset

That pretty much catches you up-to-date with the goings on in my life. As you can tell, it's been a great summer so far. I'm really looking forward to the fall too. Broncos season, a trip to Hawaii, learning new technologies, talking about them at Devoxx and a new gig.

I've decided to leave Overstock because I'm a die-hard Broncos fan and I can't work for a company that supports the Raiders during football season. There's a good chance I'll be back after the season, just in time for The Greatest Snow on Earth. ;)

This weekend, my parents are meeting us in Winter Park for Labor Day weekend. We plan on fishing, hiking, smiling and enjoying each other's company a whole lot. Tomorrow is Jack's birthday. I gotta run ... it's time to go buy a bike, play a little golf, hit the pool and go to the BBQ before tonight's CD Release Party.

Posted in General at Aug 27 2011, 01:50:52 PM MDT 1 Comment

Hyperproductive JSF 2.0 with Ed Burns at Jazoon

This morning, I attended Ed Burn's Talk on Hyperproductive JSF 2.0 at Jazoon. As you might know, I've been a critic of JSF for many years. However, it is one of the most used Java web frameworks, so I was hoping to learn how it's improved in the latest version. Below are my notes from Ed's presentation.

Ed's Plan for our Time Investment:

  1. Define a productive development environment
  2. JSF for greenfield and brownfield projects
  3. List the top 9 productivity killers with JSF projects and solutions

"I am always doing that which I cannot do, in order that I may learn how to do it." -- Pablo Picasso

Software is an executable representation of knowledge, a byproduct of learning how to solve a problem. Knowledge is something that changes as more information comes in. A productive environment makes it as easy as possible to learn how to solve a problem. Learning is an iterative process. Early iterations don't need to be optimal. Later iterations do ... and they need to be maintainable. First is the hardest. Fast iterations are they key. Spring Roo and Play are examples of frameworks that make the first iteration very fast.

You should use a tool to jumpstart JSF development: copy from an old project, use a Maven archetype or use your IDE. With greenfield development, you don't have to bother learning the byproduct of other people's learning. It's a great opportunity to pad your resume with the latest hot technologies. With brownfield development, it's vitally important to understand the existing solution and hidden assumptions. You're also much more constrained in your technology choices. If you want to change, you'll need to come up with a migration strategy, which can be difficult. JSF works well for both because it's not just a runtime framework, it's also a conceptual framework. You need to understand how your framework handles data conversion, validation, page flow, persistence integration, I18N, L10N, A11Y, Web standards and user friendliness.

Top 9 JSF Productivity Killers:

  1. Time wasting deployment step
  2. The perils of "there's more than one way to do it"
  3. Lengthy and painful developer on-boarding process
  4. Misused logging and misunderstood error messages
  5. Phantoms
  6. Under-utilized developer tools
  7. Premature optimization
  8. Difficulty in doing TDD
  9. Lack of an app framework

Time wasting deployment step
ZeroTurnaround solves this problem with JRebel, but there's other ways to do it. Some of the killers of flow state: 1) one large war file, 2) underutilizing dynamic language features, 3) complex server environment and 4) build process is redoing work unnecessarily. To stop the time wasting deployment step, the most important things you can do are as follows:

  • Configure your IDE correctly. In Eclipse, compile directly into WEB-INF/classes and use continuous compilation. With NetBeans, use GlassFish.
  • Don't do control-flow programming in XML.

Ed then showed a simple demo that showed how you can use Groovy to create a JSF UI Component. He also mentioned that Groovy can be used to author any JSF artifact. The benefit of this is you can simply edit and save a .groovy file without having to recompile or redeploy. Unfortunately, using Groovy didn't eliminate the XML syntax for pages or the XML for defining UI components.

The perils of "there's more than one way to do it"
JSF is very flexible, but flexibility is, more often than not, abused. There's a lack of convention for common things (e.g. master-detail, JSF concepts like converter, validator, etc.). The best way to fix this is to establish the norms for a project and stick with them. For example, Neil Griffin has a good blog entry for the different kind of managed beans you can create. Develop recommendations like Neil's and use them on all your projects.

Lengthy developer on-boarding process
Stick with standards when possible (at least have a common project description and build system across projects). Be committed to periodic cleanup cycles, including documenting for re-use. Pick one JSF component library and stick with it. Support for mixing and switching component libraries has improved with JSF 2, but it's still recommended you use only one.

Misused logging and misunderstood error messages
JSF is notorious for cryptic error messages and very long stack traces. It's still a problem, but the JSF Team is still working on improving them. Good tip: use the <ui:debug> tag. Its recordStateSize="true" attribute can be especially useful. If you're using PrimeFaces, add trace=true to request URLs.

Phantoms
Phantoms is when running code is not the same as the code you are modifying or wrong version of library gets picked up. You should have the capability to hit breakpoints anywhere in your entire software stack, including core Java sources. This is one of the most useful things about open source software. Solutions to phantoms: 1) put a timestamp on every redeploy and have the timestamp appear in the system log 2) write the running library stack to the system log (each library and version being used) and make it easy to compare one developer's runtime stack with another's 3) consider doing all work in tightly controlled VMs (checkout the VM at the beginning of the day, do your work, commit your changes and throw your VM away at the end of the day).

Under-utilizing developer tools
Make sure everyone has the fastest machines available and as much screen real estate as desired. Hardware is much cheaper than developer time. Another tip is to use Hudson as your butler. It's not just the team CI server. In other words, take advantage of automation wherever you can.

Premature Optimization
Keep in mind the trade-offs between readability and performance. When using frameworks such as JSF, don't try to outsmart the implementation. Rather, use the framework as intended and use open-source contributions to treat performance problems. Example, EL expressions got a lot faster between EE5 and EE6. If you spent time trying to optimize EL expressions, you might've been wasting your time.

Difficulty in doing TDD
Try to figure out why TDD is difficult in your company. For JSF, strongly consider JBoss's JSFUnit. Write your testcases to extend from Cactus ServletTestCase and leverage HtmlUnit (JSFUnit does this for you).

Lack of an app framework
Create common components: login panel, CRUD components, etc. If you don't have an app framework, build one over time.

Conclusion
This was an interesting talk by Ed. The dynamics of the room where a bit interesting. Jazoon is held in a movie theater, much like Devoxx. However, it appears there's a spotlight on the speaker that makes it very difficult to see the audience. I don't remember having this problem at Devoxx. Ed asked the audience quite a few questions, but it seemed he had a lot of difficulty in seeing if folks raised their hands. This made for some periods of awkward silence.

Personally, I was hoping to learn some new whizbang tips about JSF that I was not aware of. Unfortunately, I didn't learn anything new and wasn't that impressed with the Groovy demo.

I think Ed's tips about things outside of JSF were good, especially buying developers good hardware. I've seen many companies, including my current client, skimp on developer hardware and cause developer frustration because of it. I think it's great when companies provide developers top-of-the-line hardware and eliminate frustration over CPU and memory resources. LinkedIn and Time Warner Cable both provide their developers with Mac Pros and MacBook Pros as well as huge monitors. IMO, this is one of the best benefits you can provide your engineers.

Posted in Java at Jun 23 2011, 04:53:10 AM MDT 3 Comments

Java Web Application Security - Part I: Java EE 6 Login Demo

Back in February, I wrote about my upcoming conferences:

In addition to Vegas and Poland, there's a couple other events I might speak at in the next few months: the Utah Java Users Group (possibly in April), Jazoon and ÜberConf (if my proposals are accepted). For these events, I'm hoping to present the following talk:

Webapp Security: Develop. Penetrate. Protect. Relax.
In this session, you'll learn how to implement authentication in your Java web applications using Spring Security, Apache Shiro and good ol' Java EE Container Managed Authentication. You'll also learn how to secure your REST API with OAuth and lock it down with SSL.

After learning how to develop authentication, I'll introduce you to OWASP, the OWASP Top 10, its Testing Guide and its Code Review Guide. From there, I'll discuss using WebGoat to verify your app is secure and commercial tools like webapp firewalls and accelerators.

Fast forward a couple months and I'm happy to say that I've completed my talk at the Utah JUG and it's been accepted at Jazoon and Über Conf. For this talk, I created a presentation that primarily consists of demos implementing basic, form and Ajax authentication using Java EE 6, Spring Security and Apache Shiro. In the process of creating the demos, I learned (or re-educated myself) how to do a number of things in all 3 frameworks:

  • Implement Basic Authentication
  • Implement Form-based Authentication
  • Implement Ajax HTTP -> HTTPS Authentication (with programmatic APIs)
  • Force SSL for certain URLs
  • Implement a file-based store of users and passwords (in Jetty/Maven and Tomcat standalone)
  • Implement a database store of users and passwords (in Jetty/Maven and Tomcat standalone)
  • Encrypt Passwords
  • Secure methods with annotations

For the demos, I showed the audience how to do almost all of these, but skipped Tomcat standalone and securing methods in the interest of time. In July, when I do this talk at ÜberConf, I plan on adding 1) hacking the app (to show security holes) and 2) fixing it to protect it against vulnerabilities.

I told the audience at UJUG that I would post the presentation and was planning on recording screencasts of the various demos so the online version of the presentation would make more sense. Today, I've finished the first screencast showing how to implement security with Java EE 6. Below is the presentation (with the screencast embedded on slide 10) as well as a step-by-step tutorial.


Java EE 6 Login Tutorial

Download and Run the Application
To begin, download the application you'll be implementing security in. This app is a stripped-down version of the Ajax Login application I wrote for my article on Implementing Ajax Authentication using jQuery, Spring Security and HTTPS. You'll need Java 6 and Maven installed to run the app. Run it using mvn jetty:run and open http://localhost:8080 in your browser. You'll see it's a simple CRUD application for users and there's no login required to add or delete users.

Implement Basic Authentication
The first step is to protect the list screen so people have to login to view users. To do this, add the following to the bottom of src/main/webapp/WEB-INF/web.xml:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>users</web-resource-name>
        <url-pattern>/users</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>ROLE_ADMIN</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Java EE Login</realm-name>
</login-config>

<security-role>
    <role-name>ROLE_ADMIN</role-name>
</security-role>

At this point, if you restart Jetty (Ctrl+C and jetty:run again), you'll get an error about a missing LoginService. This happens because Jetty doesn't know where the "Java EE Login" realm is located. Add the following to pom.xml, just after </webAppConfig> in the Jetty plugin's configuration.

<loginServices>
    <loginService implementation="org.eclipse.jetty.security.HashLoginService">
        <name>Java EE Login</name>
        <config>${basedir}/src/test/resources/realm.properties</config>
    </loginService>
</loginServices>

The realm.properties file already exists in the project and contains user names and passwords. Start the app again using mvn jetty:run and you should be prompted to login when you click on the "Users" tab. Enter admin/admin to login.

After logging in, you can try to logout by clicking the "Logout" link in the top-right corner. This calls a LogoutController with the following code that logs the user out.

public void logout(HttpServletResponse response) throws ServletException, IOException {
    request.getSession().invalidate();
    response.sendRedirect(request.getContextPath());
}

You'll notice that clicking this link doesn't log you out, even though the session is invalidated. The only way to logout with basic authentication is to close the browser. In order to get the ability to logout, as well as to have more control over the look-and-feel of the login, you can implement form-based authentication.

Implement Form-based Authentication
To change from basic to form-based authentication, you simply have to replace the <login-config> in your web.xml with the following:

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login.jsp</form-login-page>
        <form-error-page>/login.jsp?error=true</form-error-page>
    </form-login-config>
</login-config>

The login.jsp page already exists in the project, in the src/main/webapp directory. This JSP has 3 important elements: 1) a form that submits to "${contextPath}/j_security_check", 2) an input element named "j_username" and 3) an input element named "j_password". If you restart Jetty, you'll now be prompted to login with this JSP instead of the basic authentication dialog.

Force SSL
Another thing you might want to implement to secure your application is forcing SSL for certain URLs. To do this on the same <security-constraint> you already have in web.xml, add the following after </auth-constraint>:

<user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>

To configure Jetty to listen on an SSL port, add the following just after </loginServices> in your pom.xml:

<connectors>
    <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <forwarded>true</forwarded>
        <port>8080</port>
    </connector>
    <connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
        <forwarded>true</forwarded>
        <port>8443</port>
        <maxIdleTime>60000</maxIdleTime>
        <keystore>${project.build.directory}/ssl.keystore</keystore>
        <password>appfuse</password>
        <keyPassword>appfuse</keyPassword>
    </connector>
</connectors>

The keystore must be generated for Jetty to start successfully, so add the keytool-maven-plugin just above the jetty-maven-plugin in pom.xml.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>keytool-maven-plugin</artifactId>
    <version>1.0</version>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <id>clean</id>
            <goals>
                <goal>clean</goal>
            </goals>
        </execution>
        <execution>
            <phase>generate-resources</phase>
            <id>genkey</id>
            <goals>
                <goal>genkey</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <keystore>${project.build.directory}/ssl.keystore</keystore>
        <dname>cn=localhost</dname>
        <keypass>appfuse</keypass>
        <storepass>appfuse</storepass>
        <alias>appfuse</alias>
        <keyalg>RSA</keyalg>
    </configuration>
</plugin>

Now if you restart Jetty, go to http://localhost:8080 and click on the "Users" tab, you'll get a 403. What the heck?! When this first happened to me, it took me a while to figure out. It turns out that Jetty doesn't redirect to HTTPS when using Java EE authentication, so you have to manually type in https://localhost:8443/ (or add a filter to redirect for you). If you deployed this same application on Tomcat (after enabling SSL), it would redirect for you.

Store Users in a Database
Finally, to store your users in a database instead of file, you'll need to change the <loginService> in the Jetty plugin's configuration. Replace the existing <loginService> element with the following:

<loginServices>
    <loginService implementation="org.eclipse.jetty.security.JDBCLoginService">
        <name>Java EE Login</name>
        <config>${basedir}/src/test/resources/jdbc-realm.properties</config>
    </loginService>
</loginServices>

The jdbc-realm.properties file already exists in the project and contains the database settings and table/column names for the user and role information.

jdbcdriver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost/appfuse
username = root
password =
usertable = app_user
usertablekey = id
usertableuserfield = username
usertablepasswordfield = password
roletable = role
roletablekey = id
roletablerolefield = name
userroletable = user_role
userroletableuserkey = user_id
userroletablerolekey = role_id
cachetime = 300

Of course, you'll need to install MySQL for this to work. After installing it, you should be able to create an "appfuse" database and populate it using the following commands:

mysql -u root -p -e 'create database appfuse'
curl https://gist.github.com/raw/958091/ceecb4a6ae31c31429d5639d0d1e6bfd93e2ea42/create-appfuse.sql > create-appfuse.sql
mysql -u root -p appfuse < create-appfuse.sql

Next you'll need to configure Jetty so it has MySQL's JDBC Driver in its classpath. To do this, add the following dependency just after the <configuration> element (before <executions>) in pom.xml:

<dependencies>
    <!-- MySQL for JDBC Realm -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.14</version>
    </dependency>
</dependencies>

Now run the jetty-password.sh file in the root directory of the project to generate a password of your choosing. For example:

$ sh jetty-password.sh javaeelogin
javaeelogin
OBF:1vuj1t2v1wum1u9d1ugo1t331uh21ua51wts1t3b1vur
MD5:53b176e6ce1b5183bc970ef1ebaffd44

The last two lines are obfuscated and MD5 versions of the password. Update the admin user's password to this new value. You can do this with the following SQL statement.

UPDATE app_user SET password='MD5:53b176e6ce1b5183bc970ef1ebaffd44' WHERE username = 'admin';

Now if you restart Jetty, you should be able to login with admin/javaeelogin and view the list of users.

Summary
In this tutorial, you learned how to implement authentication using standard Java EE 6. In addition to the basic XML configuration, there's also some new methods in HttpServletRequest for Java EE 6 and Servlet 3.0:

  • authenticate(response)
  • login(user, pass)
  • logout()

This tutorial doesn't show you how to use them, but I did play with them a bit as part of my UJUG demo when implementing Ajax authentication. I found that login() did work, but it didn't persist the authentication for the users session. I also found that after calling logout(), I still needed to invalidate the session to completely logout the user. There are some additional limitations I found with Java EE authentication, namely:

  • No error messages for failed logins
  • No Remember Me
  • No auto-redirect from HTTP to HTTPS
  • Container has to be configured
  • Doesn’t support regular expressions for URLs

Of course, no error messages indicating why login failed is probably a good thing (you don't want to tell users why their credentials failed). However, when you're trying to figure out if your container is configured properly, the lack of container logging can be a pain.

In the next couple weeks, I'll post Part II of this series, where I'll show you how to implement this same set of features using Spring Security. In the meantime, please let me know if you have any questions.

Posted in Java at May 05 2011, 04:58:00 PM MDT 9 Comments

The Greatest Snow on Earth

Last week, I traveled on my monthly trip to Utah to work on-site at Overstock. Unlike previous visits, snow was in the forecast and it didn't disappoint. I woke up early on Friday, worked a few hours and then met a couple co-workers at the office at 8. We arrived at Solitude by 8:40 and were in line for the lift by 8:55. We were the 5th chair on the lift and quickly skied to The Summit Lift. It was here we found thigh-deep powder and face shots on every run. The video below has shot by my co-worker, Eric. You can also view it on YouTube. The face shots start around 0:45.

After an awesome morning of skiing, I returned to work and later picked up Trish from the airport for a weekend of powder. When I started working at Overstock, I told myself that I'd buy a pair of "Utah Skis" if the powder was good. It seemed like the right time, so I picked up some Bluehouse Powder Skis on the way back from the airport. That night, we saw Hot Buttered Rum and woke up early for 27" of fresh powder at Alta.

Free Heeling

The skiing was incredible all day and it never stopped snowing. That night, we headed to The Canyons and stayed slopeside at The Hyatt. We got upgraded to a great room and enjoyed some nice views.

The Hyatt Bluehouse Awesomeness View at The Hyatt

We slept in on Sunday, grabbed some breakfast and hopped on the lift around noon. It was a Bluebird Day and we skied as much of the hard stuff as we could find.

The Canyons The 9990 Lift 9990's Fun Runs Into The Light

Hiking to the top of 9990 Top of 9990

Several weeks ago, I said I thought Colorado's powder was better than Utah's. After experiencing knee-deep powder at Solitude and sweet, fluffy powder at Alta, I'm officially changing my stance. In my opinion, Utah has the greatest powder on earth. If Colorado happens to get that much powder, and I get to ski it, I'd be more than happy to reconsider.

Posted in General at Mar 02 2011, 12:11:59 AM MST 3 Comments

Implementing Extensionless URLs with Tapestry, Spring MVC, Struts 2 and JSF

For the past couple of weeks, I've spent several evening hours implementing extensionless URLs in AppFuse. I've been wanting to do this ever since I wrote about how to do it a few years ago. This article details my experience and will hopefully help others implement this feature in their webapps.

First of all, I used the UrlRewriteFilter, one of my favorite Java open source projects. Then I followed a pattern I found in Spring's "mvc-basic" sample app from MVC Simplifications in Spring 3.0. The app has since changed (because SpringSource integrated UrlRewriteFilter-type functionality in Spring MVC), but the pattern was basically path-matching instead of extension-mapping. That is, the "dispatcher" for the web framework was mapped to /app/* instead of *.html.

Prior to the move to extensionless URLs, AppFuse used *.html for its mapping and this seemed to cause users problems when they wanted to serve up static HTML files. To begin with, I removed all extensions from URLs in tests (Canoo WebTest is used for testing the UI). I also did this for any links in the view pages and redirects in the Java code. This provided a decent foundation to verify my changes worked. Below are details about each framework I did this for, starting with the one that was easiest and moving to hardest.

Tapestry 5
Tapestry was by far the easiest to integrate extensionless URLs into. This is because it's a native feature of the framework and was already integrated as part of Serge Eby's Tapestry 5 implementation. In the end, the only things I had to do where 1) add a couple entries for CXF (mapped to /services/*) and DWR (/dwr/*) to my urlrewrite.xml and 2) change the UrlRewriteFilter so it was only mapped to REQUEST instead of both REQUEST and FORWARD. Below are the mappings I added for CXF and DWR.

<urlrewrite default-match-type="wildcard">
    ...
    <rule>
        <from>/dwr/**</from>
        <to>/dwr/$1</to>
    </rule>
    <rule>
        <from>/services/**</from>
        <to>/services/$1</to>
    </rule>
</urlrewrite>

Spring MVC
I had a fair amount of experience with Spring MVC and extensionless URLs. Both the Spring MVC applications we developed last year at Time Warner Cable used them. To change from a *.html mapping to /app/* was pretty easy and involved removing more code than I added. Previously, I had a StaticFilter that looked for HTML files and if it didn't find them, it dispatched to Spring's DispatcherServlet. I was able to remove this class and make the web.xml file quite a bit cleaner.

To make UrlRewriteFilter and Spring Security play well together, I had to move the securityFilter so it came after the rewriteFilter and add an INCLUDE dispatcher so included JSPs would have a security context available to them.

<filter-mapping>
    <filter-name>rewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>securityFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

The only other things I had to change were security.xml and dispatcher-servlet.xml to remove the .html extensions. The urlrewrite.xml file was fairly straightforward. I used the following at the bottom as a catch-all for dispatching to Spring MVC.

<rule>
    <from>/**</from>
    <to>/app/$1</to>
</rule>
<outbound-rule>
    <from>/app/**</from>
    <to>/$1</to>
</outbound-rule>

Then I added a number of other rules for j_security_check, DWR, CXF and static assets (/images, /scripts, /styles, /favicon.ico). You can view the current urlrewrite.xml in FishEye. The only major issue I ran into was that Spring Security recorded protected URLs as /app/URL so I had to add a rule to redirect when this happened after logging in.

<rule>
    <from>/app/**</from>
    <to last="true" type="redirect">%{context-path}/$1</to>
</rule>

Struts 2
Using extensionless URLs with Struts 2 is likely pretty easy thanks to the Convention Plugin. Even though this plugin is included in AppFuse, it's not configured with the proper constants and I have struts.convention.action.disableScanning=true in struts.xml. It looks like I had to do this when I upgraded from Struts 2.0.x to Struts 2.1.6. It's true AppFuse's Struts 2 support could use a bit of love to be aligned with Struts 2's recommended practices, but I didn't want to spend the time doing it as part of this exercise.

With Struts 2, I tried the path-mapping like I did with Spring MVC, but ran into issues. Instead, I opted to use an ".action" extension by changing struts.action.extension from "html" to "action," in struts.xml. Then I had to do a bunch of filter re-ordering and dispatcher changes. Before, with a .html extension, I had all filters mapped to /* and in the following order.

Filter NameDispatchers
securityFilter request
rewriteFilter request, forward
struts-prepare request
sitemesh request, forward, include
staticFilter request, forward
struts request

Similar to Spring MVC, I had to remove the rewriteFilter in front of the securityFilter and I was able to remove the staticFilter. I also had to map the struts filter to *.action instead of /* to stop Struts from trying to catch static asset and DWR/CXF requests. Below is the order of filters and their dispatchers that seems to work best.

Filter NameDispatchers
rewriteFilter request
securityFilter request, forward, include
struts-prepare request, forward
sitemesh request, forward, include
struts forward

From there, it was a matter of modifying urlrewrite.xml to have the following catch-all and rules for static assets, j_security_check and DWR/CXF.

<rule match-type="regex">
    <from>^([^?]*)/([^?/\.]+)(\?.*)?$</from>
    <to last="true">$1/$2.action$3</to>
</rule>
<outbound-rule match-type="regex">
    <from>^(.*)\.action(\?.*)?$</from>
    <to last="false">$1$2</to>
</outbound-rule>

JSF
JSF was by far the most difficult to get extensionless URLs working with. I'm not convinced it's impossible, but I spent a several hours over a few days and was unsuccessful in completely removing them. I was able to make things work so I could request pages without an extension, but found when clicking buttons and links, the extension would often show up in the URL. I'm also still using JSF 1.2, so it's possible that upgrading to 2.0 would solve many of the issues I encountered.

For the time being, I've changed my FacesServlet mapping from *.html to *.jsf. As with Struts, I had issues when I tried to map it to /app/*. Other changes include changing the order of dispatchers and filters, the good ol' catch-all in urlrewrite.xml and modifying security.xml. For some reason, I wasn't able to get file upload working without adding an exception to the outbound-rule.

<rule match-type="regex">
    <from>^([^?]*)/([^?/\.]+)(\?.*)?$</from>
    <to last="true">$1/$2.jsf</to>
</rule>
<outbound-rule match-type="regex">
  <!-- TODO: Figure out how to make file upload work w/o using *.jsf -->
    <condition type="path-info">selectFile</condition>
    <from>^(.*)\.jsf(\?.*)?$</from>
    <to last="false">$1$2</to>
</outbound-rule>

I also spent a couple hours trying to get Pretty Faces to work. I wrote about my issues on the forums. I tried writing a custom Processor to strip the extension, but found that I'd get into an infinite loop where the processor kept getting called. To workaround this, I tried using Spring's RequestContextHolder to ensure the processor only got invoked once, but that proved fruitless. Finally, I tried inbound and outbound custom processors, but failed to get those working. The final thing I tried was url-mappings for each page in pretty-config.xml.

<url-mapping>
  <pattern value="/admin/users"/>
  <view-id value="/admin/users.jsf"/>
</url-mapping>
<url-mapping>
  <pattern value="/mainMenu"/>
  <view-id value="/mainMenu.jsf"/>
</url-mapping>

The issue with doing this was that some of the navigation rules in my faces-config.xml stopped working. I didn't spend much time trying to diagnose the problem because I didn't like having to add an entry for each page in the application. The one nice thing about Pretty Faces is it did allow me to do things like the following, which I formerly did with a form that auto-submitted when the page loaded.

<url-mapping>
  <pattern value="/passwordHint/#{username}"/>
  <view-id value="/passwordHint.jsf"/>
  <action>#{passwordHint.execute}</action>
</url-mapping>

Conclusion
My journey implementing extensionless URLs was an interesting one, and I solidified my knowledge about ordering of filters, dispatchers and the UrlRewriteFilter. I still think I have more to learn about properly implementing extensionless URLs in Struts 2 and JSF and I hope to do that in the near future. I believe Struts' Convention Plugin will help me and JSF 2 + Pretty Faces will hopefully work nicely too. Of course, it'd be great if all Java Web Frameworks had an easy mechanism for producing and consuming extensionless URLs. In the meantime, thank goodness for the UrlRewriteFilter.

If you'd like to try AppFuse and its shiny new URLs, see the QuickStart Guide and choose the 2.1.0-SNAPSHOT version.

Posted in Java at Feb 10 2011, 04:53:27 PM MST 10 Comments

My Comparing JVM Web Frameworks Presentation from Devoxx 2010

This week, I've been having a great time in Antwerp, Belgium at the Devoxx Conference. This morning, I had the pleasure of delivering my Comparing JVM Web Frameworks talk. I thoroughly enjoyed giving this presentation, especially to such a large audience. You can view the presentation below (if you have Flash installed) or download it here.

Unlike previous years, I chose to come up with a spreadsheet matrix that shows why I chose the 5 I did. This spreadsheet and rankings given to each framework are likely to be debated, as I don't know all the frameworks as well as I'd like to. Also, the missing column on this spreadsheet is a "weighting" column where you can prioritize certain criteria like I've done in the past when Comparing Ajax Frameworks. If you believe there are incorrect numbers, please let me know and I'll try to get those fixed before I do this talk again at The Rich Web Experience.

One thing that doesn't come across in this presentation is that I believe anyone can use this matrix, and weightings, to make any of these frameworks come out on top. I also believe web frameworks are like spaghetti sauce in The Ketchup Conundrum. That is, the only way to make more happy spaghetti sauce lovers was to make more types of spaghetti sauce. You can read more about this in my There is no "best" web framework article.

Update: If you disagree with the various ratings I gave to web frameworks in this presentation, please provide your opinions by filling out this survey. Thanks to Sebastien Arbogast for setting this up.

Update: Sebastien has posted his survey results at JVM Web Framework Survey, First Results.

Update 12/6: A video of this presentation is now available on Parleys.com.

P.S. My current gig is ending in mid-December. If you're looking for a UI Architect with a passion for open source frameworks, please let me know.

Posted in Java at Nov 18 2010, 05:23:10 AM MST 39 Comments

RE: Moving from Spring to Java EE 6: The Age of Frameworks is Over

Last Tuesday, Cameron McKenzie wrote an interesting article on TheServerSide titled Moving from Spring to Java EE 6: The Age of Frameworks is Over. In this article, Cameron says the following:

J2EE represents the past, and Java EE 6 represents the future. Java EE 6 promises us the ability to go beyond frameworks. Frameworks like Spring are really just a bridge between the mistakes of the J2EE past and the success of the Java EE 6 future. Frameworks are out, and extensions to the Java EE 6 platform are in. Now is the time to start looking past Spring, and looking forward to Seam and Weld and CDI technologies.

He then links to an article titled Spring to Java EE - A Migration Experience, an article written by JBoss's Lincoln Baxter. In this article, Lincoln talks about many of the technologies in Java EE 6, namely JPA, EJB, JSF, CDI and JAX-RS. He highlights all the various XML files you'll need to know about and the wide variety of Java EE 6 application servers: JBoss AS 6 and GlassFish v3.

I don't have a problem with Lincoln's article, in fact I think it's very informative and some of the best documentation I've seen for Java EE 6.

I do have some issues with Cameron's statements that frameworks are mistakes of the J2EE past and that Java EE 6 represents the future. Open source frameworks made J2EE successful. Struts and Hibernate came out in the early days of J2EE and still exist today. Spring came out shortly after and has turned into the do-everything J2EE implementation it was trying to fix. Java EE 6 might be a better foundation to build upon, but it's certainly not going to replace frameworks.

To prove my point, let's start by looking at the persistence layer. We used to have Hibernate based on JDBC, now we have JPA implementations built on top of the JPA API. Is JPA a replacement for all persistence frameworks? I've worked with it and think it's a good API, but the 2.0 version isn't available in a Maven repo and Alfresco recently moved away from Hibernate (which == JPA IMO) to iBATIS for greater data access layer control and scalability. Looks like the age of frameworks isn't over for persistence frameworks.

The other areas that Java EE 6 covers that I believe frameworks will continue to excel in: EJB, CDI, JSF and JAX-RS. Personally, I don't have a problem with EJB 3 and think it's a vast improvement on EJB 2.x. I don't have an issue with CDI either, and as long as it resembles Guice for dependency injection, it works for me. However, when you get into the space I've been living in for the last couple years (high-traffic public internet sites), EJB and things like the "conversation-scope" feature of CDI don't buy you much. The way to make web application scale is to eliminate state and cache as much as possible, both of which Java EE doesn't provide much help for. In fact, to disable sessions in a servlet-container, you have to write a Filter like the following:

public class DisabledSessionFilter extends OncePerRequestFilter {

    /**
     * Filters requests to disable URL-based session identifiers.
     */
    @Override
    protected void doFilterInternal(final HttpServletRequest request,
                                    final HttpServletResponse response,
                                    final FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) {

            @Override
            public HttpSession getSession(final boolean create) {
                if (create) {
                    throw new UnsupportedOperationException("Session support disabled");
                }
                return null;
            }

            @Override
            public HttpSession getSession() {
                throw new UnsupportedOperationException("Session support disabled");
            }
        };

        // process next request in chain
        chain.doFilter(wrappedRequest, response);
    }
}

What about JAX-RS? Does it replace the need for frameworks? I like the idea of having a REST API in Java. However, its reference implementation is Jersey, which seems more like a framework than just Java EE. If you choose to use JAX-RS in your application, you still have to choose between CXF, Jersey, RESTEasy and Restlet. I compared these frameworks last year and found the Java EE implementation lacking in the features I needed.

Finally, let's talk about my-least-framework-web-framework: JSF. The main reason I don't like JSF is because of its 1.x version. JSF 1.0 was released a year before the Ajax term was coined (see timeline below). Not only did it take forever to develop as a spec, but it tried to be a client-component framework that was very stateful by default.

History of Web Frameworks

Now that JSF 2.0 is out, it has Ajax integrated and allows you to use GET instead of POST-for-everything. However, the only people that like Ajax integrated into their web frameworks are programmers scared of JavaScript (who probably shouldn't be developing your UI). Also, the best component development platform for the web is JavaScript. I recommend using an Ajax framework for your components if you really want a rich UI.

Sure you can use the likes of Tapestry and Wicket if you like POJO-based web development, but if you're looking to develop a webapp that's easy to maintain and understand, chances are that you'll do much better with traditional MVC frameworks like Spring MVC and Struts 2. The simplicity and popularity of Rails and Grails further emphasize that developers prefer these types of web frameworks.

Another reason I don't like JSF: there's very few developers in the wild happy with it. The major promoters of JSF are book authors, trainers, Java EE Vendors and MyFaces developers. Whenever I speak at conferences, I ask folks to raise their hands for the various web frameworks they're using. I always ask the JSF users to keep their hands up if they like it. Rarely do they stay up.

So it looks like we still need web frameworks.

Eberhard Wolff has an interesting post where he defends Spring and talks about the productivity comparisons between Spring and Java EE. He recommends using Grails or Spring Roo if you want the level of productivity that Ruby on Rails provides. That's a valid recommendation if you're building CRUD-based webapps, but I haven't developed those in quite some time. Nowadays, the apps I develop are true SOFEA apps, where the backend serves up XML or JSON and the frontend client is HTML/JavaScript/CSS, Android, iPad or Sony Blu-Ray players. On my current project, our services don't even talk to a database, they talk to a CMS via RESTful APIs. We use Spring's RestTemplate for this and HttpClient when it doesn't have the features we need. Not much in Java EE 6 for this type of communication. Sure, Jersey has a client, but it's certainly not part of the Java EE spec.

As far as getting Ruby on Rails' zero-turnaround productivity, I don't need Grails or Spring Roo, I simply use IDEA and JRebel.

Conclusion
I don't see how new features in Java EE 6 can mean the age of frameworks is over. Java SE and J2EE have always been foundations for frameworks. The Java EE 6 features are often frameworks in themselves that can be used outside of a Java EE container. Furthermore, Java EE 6 doesn't provide all the features you need to build a high-scale web app today. There's no caching, no stateless web framework that can serve up JSON and HTML and no hot-reload productivity enhancements like JRebel. Furthermore, there's real excitement in Javaland for languages like Scala, Groovy and JRuby. All of these languages have web frameworks that've made many developers happy.

Here's to the Age of Frameworks - may it live as long as the JVM!

P.S. If you'd like to hear me talk about web frameworks on the JVM, I'll be speaking at The Colorado Springs Open Source Meetup and Devoxx 2010 in the near future.

Posted in Java at Oct 16 2010, 03:19:07 PM MDT 37 Comments