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 "free sex movies for men non blog". 1,227 entries found.

You can also try this same search on Google.

Why the bias against JSF?

In my last post about InfoQ's Top 20 Web Frameworks for the JVM, I received a thought-provoking comment from henk53:

There is one little thing that does bother me in those presentations, and that's your fairly obvious bias against JSF.
...
If you are presenting yourself as, more or less, an authority on comparing web frameworks, then having a fairly obvious biased against one of them is just peculiar. I, all of my team, and various clients distrust your ranking of JSF. We do look at your data if the choice is between other frameworks, but as soon as JSF comes into the picture we just look elsewhere.

I'm not really sure where this bias comes from. Yes, JSF 1.0 sucked and 1.2 was only marginally better, but 2.0 is really cool and productive and there are SUPERB component and utility libraries now like PrimeFaces and OmniFaces. As a researcher of this topic I think you should keep up the date and not stick to some old grudge.

This is true, I am biased against JSF. It all started with my first JSF experience back in August 2004. If you remember correctly, 2004 was a big year: JSF 1.0, Spring 1.0 and Flex 1.0 were all released. The "AJAX" term was coined in early 2005.

History of Web Frameworks

By 2007 and 2008, JSF still hadn't gotten any better. In late 2009, JSF 2.0 was released and I upgraded in March 2011. As you can see from the aforementioned post, I ran into quite a few issues upgrading. JSF was also the hardest one to get working with extension-less URLs.

Most of my issues with JSF come from having maintained an application built with it since 2004. If I were to start a new application without any legacy migration issues, I imagine it wouldn't be as difficult. However, if you compare it to Struts 2 and Spring MVC, I've had little-to-no issues upgrading those applications over the years.

Also, I'm not just biased against JSF, but most component-based web frameworks. Just ask the Tapestry and Wicket folks. They've felt my criticisms over the years. My reason for preferring request-based frameworks like Struts 2/Spring MVC and Grails/Play has been because I've never seen the appeal in component-based frameworks. Often I've found that their components are just widgets that you can get from any decent JavaScript framework. And chances are that JavaScript framework can work with any web framework. Also, I've worked on a lot of high-traffic web applications that require statelessness for scalability.

I see the value in component-based frameworks, I just don't think components should be authored on the server-side. Most of the Java-based component frameworks require 2+ files for components (one for the component, one for the view, possibly one for the config). I love GWT's component concept in that you can just extract a class and re-use it. With JS frameworks, you can often just include a script. These days, when I think of good component-based frameworks, I think of jQuery UI and Twitter Bootstrap.

All that being said, there's a lot of folks praising JSF 2 (and PrimeFaces moreso). That's why I'll be integrating it (or merging your pull request) into the 2.3 release of AppFuse. Since PrimeFaces contains a Bootstrap theme, I hope this is a pleasant experience and my overall opinion of JSF improves.

In other component-based frameworks in AppFuse news, Tapestry 5 has gotten really fast in the last year. I imagine this is because we have a Tapestry expert, Serge Eby, working on it. And we're planning on adding Wicket in the 2.3 release.

So even though I prefer request-based frameworks with REST support and Bootstrap, that doesn't mean everyone does. I'll do my best to be less-biased in the future. However, please remember that my view on web frameworks is as a developer, not an analyst. And aren't developers supposed to be opinionated? ;)

Posted in Java at Nov 08 2012, 09:24:27 AM MST 11 Comments

InfoQ's Top 20 Web Frameworks for the JVM

Back in early October, InfoQ.com published a community research article titled Top 20 Web Frameworks for the JVM. Their goal seemed to be fairly simple:

Using the new community research tool, we at InfoQ want to get YOUR opinions on the relative importance and maturity of a variety of web frameworks that are targeted for the JVM. Please vote by dragging each practice across two dimensions – how important is the framework relative to the other frameworks, and how much is it actually used in real teams and projects.

When I first saw this article, I noticed some strange web frameworks listed. Namely, Netty, SiteMesh and Spark. I haven't heard of many folks using Netty for a web framework, but I'm sure it's possible. SiteMesh is certainly not a web framework and I've never even heard of Spark. And where is GWT and Vaadin? Regardless of the choices, I went ahead and voted.

Last week, InfoQ posted their top content for October on Facebook.

First of all, it's interesting to see that JVM Web Frameworks is still a hot topic for developers. Whenever I do my Comparing JVM Web Frameworks talk at conferences, I always see a few jabs about "he's still doing that talk!?" Yes, it seems strange that a talk I first did in 2004 is still in high demand.

Secondly, I think InfoQ does good in showing how the frameworks ranked and showing their heatmaps. Below are their rankings from 1109 participants.

InfoQ's Top 20 Web Frameworks for the JVM

According to this research, the top 5 web frameworks for the JVM are Spring MVC, Play, Grails, JSF and Struts (I hope those surveyed meant Struts 2, not Struts 1).

In my research from last February (slide 21), I ranked them (with no particular weightings) as Grails, GWT, JRuby on Rails, Spring MVC and Vaadin. So I guess you could say I got 2 out of 5 right (Grails and Spring MVC). Not bad considering InfoQ didn't even consider GWT and Vaadin.

Another intriguing data point in this study is each frameworks' heatmap. For example, below are heatmaps for the top 4 frameworks.

Spring MVC Heatmap Grails Heatmap

Play Heatmap JSF Heatmap

Notice how Grails and Spring MVC are both hotter in the bottom right corner? It seems the community's overall opinions of these two frameworks are more aligned than JSF and Play, which a fair amount of folks rank as hyped and unimportant.

What I really like about this research is it's the community's opinions, visualized. It also confirms that some of my favorite frameworks are still on top. I don't know if JSF belongs as a top framework, however it seems a lot of folks do. I recently thought about removing it from AppFuse, but decided to keep it (at least for the next release). I hope InfoQ does more research projects like this, especially if they get their list of web frameworks right.

Posted in Java at Nov 06 2012, 12:04:28 PM MST 5 Comments

Core HTML5 Canvas Book Review

Core HTML5 Canvas I've known David Geary for quite some time, from our original meeting in the blogosphere to speaking on the No Fluff Tour. At first, I had trouble respecting the guy because he was such a JSF Fanboy. However, over the years, he's switched to Ruby on Rails, GWT and now he's all about HTML5. Specifically, HTML5's <canvas> element. When David asked me if I'd like a copy of his lastest book, I jumped at the opportunity.

I received it in the mail shortly before heading to Hawaii this summer. I started reading it by the pool the next day.

I was immediately impressed that the book was printed in color. The first copy I ever saw of my Spring Primer was in color and it really popped. Geary's book does the same and I'm glad the publisher decided the extra cost of printing was worth it. In the preface (and in a recent blog post), David explains how he wrote the book code-first in the Zen tradition, so you can read it without reading. I saw him write somewhere that he spent 2 years, 60 hours per week writing it. It really shows - the sheer amount of code and knowledge in this book is amazing.

Looking back at the Table of Contents, I remember getting overwhelmed early on. Not overwhelmed in that I didn't understand how things were working, but more like "there's too much in here to try and remember it all". I haven't used algebra since high school, and right there on page 53 it says:

To do anything interesting with Canvas, you need a good basic understanding of basic mathematics, especially working with algebraic equations, trigonometry, and vectors.

Reading the book poolside wasn't a huge motivator to refresh my algebraic knowledge, but I did enjoy David's brief 10-page refresher. In Chapter 2 on Drawing, the book dives into the low-level API that canvas offers for drawing rectangles, circles and polygons. It also goes on to show you how to do gradients, patterns and shadows as well as all there is to know about paths, stroking and filling. This is when it hits you that <canvas> is more about JavaScript than HTML. In fact, it's usually only a couple lines of HTML and a whole lotta JavaScript.

In Chapter 3, you learn about text and how to work with fonts and paragraphs. David even spends 10 pages showing you how to implement a Paragraph, complete with positioning the cursor, adding new lines and working with backspace. It really makes you appreciate what HTML offers you with the good ol' <p> and <input type="text">.

Chapter 4 is where you learn about working with images and video, using offscreen canvases and working with a canvas within a canvas. I believe I was back in Colorado when I started reading this chapter. It's also where I succumbed to the fact that this was an excellent reference book and not something I was going to read, learn from and start using the next week. It feels like a book I'll refer back to many times when using <canvas> on a project. The amount of knowledge in the book seems akin to Rod Johnson's J2EE Development without EJB. I remember getting the general gist of Rod's ideas while reading the book, but not knowing how to put them into use. Then the Spring Framework was introduced and everything became clear. As I read Geary's book, I thought the same thing - someone really needs to develop a simpler API for Canvas.

As I read on, through chapters on Animations, Sprites, Physics, Collision Detection and Game Development, it hit me - maybe that's what David is doing!

Throughout the book, David builds a framework for working with Shapes, animating them and finally, for putting them to work in a gaming environment. The Ungame is nice in that it shows you how to use a game engine for building your own games. Then he goes on to show you a Pinball game that looks overly complex, but breaks it down into terms you can understand.

The last chapter is on Mobile development. It explains in detail about the viewport metatag, media queries for CSS and touch events. The section on iOS5 is good, but does make the book seem slightly outdated with iOS6 coming out next week. I'm sure all of the content is still relevant, but it almost seems like labeling it iOS5+ would've been better. In the final pages of the book, you learn how using a canvas that requires typing on a touch device might suck. David shows you how to implement a Virtual Keyboard to handle these situations, since the native keyboard won't pop up unless you're typing into HTML controls like <input> and <textarea>.

I read this book to learn more about Canvas and what it was capable of. I learned all it can do and much, much more. I learned how animations and timing can be different between browsers and how you might need to create a polyfill for requestAnimationFrame for it to work consistently.

More than anything, I recognized that this is one of the few technical books I've read in a long time that's become an instant valuable resource. With other books, the information is often available online. Not so with Geary's book. To me, it seems like the best resource available for learning and using HTML5 Canvas.

Well done, David, well done.

Posted in The Web at Sep 14 2012, 09:21:56 AM MDT 2 Comments

Happy Birthday Jack!

Eight years ago today, Jack was born. Today, it's hard to even imagine him as a baby or a toddler. But then again, we all looked quite a bit different back then.

Hiking at Red Rocks Abbie and Jack on the Train

These days, Jack has his own website and prefers to spend his free moments playing with Beyblades or his new Nintendo 3DS. He started 3rd grade this year and has excellent math and reading skills, even though he's the youngest in his class. As he grows older, he's starting to like the same things I do, particularly fishing, skiing and golfing.

Last weekend, we threw a birthday party for Jack at Julie's house. He invited some of his close friends from school and had a Beyblade tournament. Fun was had by all and you couldn't wipe the smile off his face when he went home.

Let it rip!

This fall, Jack will be playing lacrosse again and might even pass up his sister in height. He sure is a handsome kid. Happy Birthday Jack!

Jack and his buddies on his 8th birthday

Related: Jack's 5th, 4th, 3rd and 1st birthdays.

Posted in General at Aug 28 2012, 12:12:46 PM MDT 2 Comments

Refreshing Taleo's UI with HTML5, Twitter Bootstrap and CSS3

Back in December, I wrote about what I've been working on at Taleo. Shortly after finishing up the Profile Picture, Talent Card and Org Chart features for TBE, I spent two weeks doing page speed optimization. By following Web Performance Best Practices, I was able to make the TBE application twice as fast and improve its score into the low 90s.

Next, I started working on a new project - refreshing the UI. Nick, the Lead UX Designer at Taleo (at the time), had developed a number of mockups and presented it to the developers and product folks in early November. I listened to a WebEx of that meeting and learned that everyone thought it'd take 6-9 months to complete the work. They figured they could release the new design in Q3 2012.

Since I like to provide high-value for my clients, I offered to help with the redesign and do a spike to help estimate. They agreed it'd be a good use of my time and I started working on it the week before Christmas. Since I'd used Twitter Bootstrap for my Play More! app, I recommended we use it as a foundation of the redesign. They agreed and I went to work. By the end of the week, I'd made good progress and told them I thought the redesign was possible in 2-3 months (including QA and cross-browser compatibility).

When I came back to work in January, we decided to split the redesign into two phases. Rather than moving elements around and introducing new features, we decided to do that in the 2nd phase. The 1st phase would entail simply re-skinning the existing UI, with minimal HTML changes. I spent a week refining my spike and integrating it into a branch. The next week, I switched images from individual images to CSS sprites. Next, I implemented a new theming system with different colors/icons and got everything looking good in Chrome, Safari and IE8/9.

The result is something I'm quite proud of. IE8 doesn't have the rounded corners (via border-radius), but it still looks good. Forms look much better thanks to Bootstrap's styling and even jQuery UI's widgets look good thanks to jQuery UI Bootstrap. I did have to override quite a few Bootstrap styles in the process, but the result is something that doesn't look too bootstrappy.

One technique I found to be extremely useful during this process was to pair with Nick (the designer) as mentioned in Building Twitter Bootstrap. At one point, when we were trying to refine slight nuances and spacing in the UI, I paired with the Product Manager and found this to be a real time-saving effort as well.

Taleo's UI Refresh project has been a great experience for me in sharpening my CSS skills. I used quite a bit of child and sibling selectors, which work great in all the browser's we're supporting. Also, by using CSS sprites and colors (vs. images), I was able to get the manual theme-creation process down to around 15 minutes. After getting the manual process greatly reduced, I wrote a Theme Generator (based on Ant, LESS and wro4j) and got it down to mere minutes. I found Sprite Cow to be an invaluable resources for working with CSS sprites.

Below are some before and after shots of what we've been able to accomplish in the first quarter of this year.

Old UI - My View Old UI - New Employee

New UI - My View New UI - New Employee

I originally wrote this post at the end of January. We ran into some stumbling blocks shorty after its original composition: Nick (the designer) moved onto greener pastures and Oracle bought Taleo. What I didn't expect when I wrote this was to spend the next two months fixing slight bugs that occurred with spacing, alignment and dependent applications I didn't know about at the time. And then there was IE7. We didn't realize we needed to support it until mid-March. Then it took us around a month to make it all work good enough.

The good news is the UI Refresh was released a few months ago and seems to be humming along just fine. Sure, there were slight nuances and customizations we had conflicts with (clashing CSS classes), but overall it seems to have gone well. I can't thank the Bootstrap developers enough for motivating us to move to HTML5 and CSS3. Also, cheers to the excellent co-workers that helped make this happen: Murray Newton (Product Manager) and Vladimir Bazarsky. I couldn't have done it without you guys.

Posted in The Web at Aug 20 2012, 12:27:21 PM MDT 5 Comments

New Look and Feel, Designed by Gillen's Army

As part of my 10-year blogiversary, I was hoping to refresh this site with a new look and feel. A few months ago, I contacted my friend Mark Waggoner to see about getting his design help. We promptly worked out a logo/business card/website deal and Gillen's Army went to work.

I picked a logo from numerous choices in late June, finalized a business card for printing in July and received the HTML and CSS for the site on August 2nd. I started converting it to a Roller theme last week and did a whole bunch of other modifications in the process.

  • Upgraded to Roller 5.0.1.
  • Upgraded wro4j to the latest version (1.4.8.1) to workaround using a → (\2192) in CSS.
  • Changed to use jQuery and Lightbox2 for pictures.
  • Upgraded to the latest version (3.0.83) of SyntaxHighlighter. You might notice there is no longer a toolbar in this version. However, you can still double-click on code and easily copy/paste it.

In addition to these upgrades, I made a few enhancements. I converted to HTML5 (by switching the doctype), added Modernizr and a feature that detects if the sun is up in your location. If you allow your browser to send me your lat and long, I'll give you a dark theme when the sun is down and a light theme when it's daylight. I used Preston's Hunt's JavaScript Class for Sunrise and Sunset Calculations to determine isDaylight. You can also change the theme to light or dark using the small rectangles above the search box on the right. This sets a cookie and overrides the HTML5 Geo check. You can see the implementation of this logic in site.js.

The stylesheet switching doesn't happen as fast as I'd hoped (there's a flash even if using cookies), so I'll likely be converting some theme-setting logic to the server-side. The HTML5 version of the FaceBook Like Button requires you to specify the "data-colorscheme" in markup so this further supports moving to the server.

I have other minor adjustments I'd like to make, but more importantly - I wanted to get it out to you all. Tell me what you like and don't like. Among other things, the form inputs for comments and contact forms have backgrounds that might not be great for those color-impaired. Also, you can see how the iframe on the contact page has a white background instead of one based on the theme.

Here's some stats comparing my old andreas08 theme to the new darklight:

Metric andreas08 darklight
Size and Speed 167 requests, 3.6MB, 9.89s 148 requests, 3.2MB, 7.34s
YSlow 76 87
PageSpeed 91 96

Sweet! It looks like this site is faster than ever. Cheers to Mark and Gillen's Army for the new design. I dig it!

Posted in Roller at Aug 14 2012, 10:58:11 PM MDT 6 Comments

10 Years Ago...

Wouldn't you know it, I missed my 10-year blogiversary. 10 years ago yesterday, I wrote my first blog post. This was shortly after reading Dave Johnson's article about Roller. I originally started this blog to share a bunch of tips and tricks I'd learn while doing web development, particularly with Java and Struts. Since then, I've written 3,086 entries and received 13,462 comments.

I found that writing technical blog posts was a great way to remember things and share knowledge. According to Google Analytics (which doesn't track my RSS/Atom feeds), here's my most-visited blog posts since 2006.

I also started it to document my life, so I could remember the details of significant life events and fun family vacations. I wrote about Abbie's and Jack's arrival. I penned a story about growing up at the cabin, twice. In April 2004, I wrote about buying a 1966 21-window VW Bus. Yes, I'm still restoring it. No, I don't know when it'll be done. This year I hope.

I blogged about Abbie and Jack's first day of school, I wrote about almost all of Abbie's birthdays; Jack's 5th, 4th, 3rd and 1st. Some of my favorite comments are on Jack's got a bead stuck in his nose! I blogged about getting a divorce 5 years ago. I wrote about visiting the real Oktoberfest the next year.

I wrote about my Dad's retirement, my sister's wedding and my Mom's retirement.

I met Trish in June of 2010 and mentioned her name for the first time in September 2010. I introduced her to the kids in November and we started traveling the world together. We journeyed to Antwerp/Amsterdam, Fort Lauderdale/Key West, Crested Butte, Alta, Las Vegas, a hut trip in the Rockies and Kraków. And that was just in the first 6 months! We got engaged last November.

I summarized the years several times, in 2005, 2006, 2008, 2009, 2010 and 2011.

Last, but certainly not least, I'd like to thank the ones that made the last 10 years possible:

  • Keith at KGB Internet. Hosted here since day 1, for $20 month*.
  • Dave Johnson, for creating Roller and continuing to maintain it all these years.
  • Java and Tomcat, for your rock-solid stability through the years.
  • The Open Source Movement, for providing so much to write about.
  • My Family, for giving me with so many adventures and memories.

* Thank goodness he doesn't charge me for bandwidth. It's a little heavy on the bits.

Update: As part of this 10-year celebration, I've updated the look-and-feel with help from Gillen's Army.

Posted in Roller at Aug 02 2012, 12:47:19 PM MDT 3 Comments

Summer Vacation 2012 in Montana and Maui

I started writing about my summer vacations in Montana as soon as this blog gave me an opportunity: July 2003. In July 2004, I didn't travel to the cabin for the 4th, but I did in 2005. Then, 5 years ago, I started writing longer blog posts about our trips. 2008 was Raible Road Trip #12. In 2009, I spent a whole month in Montana. In 2010, I visited after my parents moved there full-time. Last year, I took Trish for the first time.

I don't know what Raible Road Trip number this year's trip was, but I'm going to go ahead and assume #17. This year wasn't exactly a vacation for me. It was what I like to call a workation. I tried to take the whole month off, but my current client needed my services. As a compromise, they agreed to let me work 20 hours per week during July. While I didn't get a chance to fully unplug, I did enjoy the reduced workload and time to spend with friends and family. And the views from The Cabin and Sugar Beach weren't bad either. ;)

Below is our trip itinerary in condensed form, complete with photos from my incredibly talented fiancé.

We embarked on our drive to Montana on June 30th, stopped for fireworks in Wyoming and spent the night in Yellowstone park. Arrived at the cabin, got to sleep in the new house for the first time, built a cabin float, drove it in the parade, went boating at Holland Lake, played golf. Journeyed to West Glacier to celebrate Dr. Barton's PhD at his sister's house. Rafted the Middlefork of the Flathead all weekend. Played some more golf and went waterskiing.

Abbie at The Cabin My Dad Happy 4th! Raible Homestead in the Swan Valley Parade
Holland Lake Patio The Girls at Double Arrow Hard to believe I caused this guy to move to Montana in 1997 Holland Lake Sunset Soy Fields in Montana
→ Trish's Montana Summer 2012 Album

On July 14th, we flew to Maui and continued to explore. Our good friend's parents have a timeshare on Sugar Beach and got us a screaming deal on lodging. We had beachfront accommodations with a pool, hot tub and sauna. We played golf on my birthday (July 16th). Visited the Old Lahaina Luau, Maui Aquarium and Coconut Festival at Grand Wailea. Drove to the summit of Haleakala. Sipped cold handcrafted ales while watched the kids boogie board. Embarked on a sunset cruise, hiked in Iao Valley, did some horseback riding along the beach, sea kayaked and snorkeled with sea turtles. Savored Shawn's excellent cooking. Flew back to Missoula (Montana), slept for 6 hours and drove 12.5 hours back to Denver on July 27th.

Api, Makao and Keaka. My Hawaiin name is Pualani I'm going to call him Honu! Abbie with the Stingray Wahoo! We did it!
Sunset sail from a catamaran in Maui. Epic! Where we stayed for 2 weeks! Epic Maui Ride Kayaking with Turtles
→ Trish's Maui Summer 2012 Album

Mahalo Montana and Maui. Thank you to our awesome friends: Mom, Dad, Owen, Jason, Ryan and Shawn. It was an incredible adventure.

Posted in General at Aug 01 2012, 09:30:27 AM MDT Add a Comment

Play vs. Grails Smackdown at ÜberConf

Play and Grails have been hyped as the most productive JVM Web Frameworks for the last couple of years. That hype has recently grown thanks to both frameworks' 2.0 releases. That's why James Ward and I decided to do a presentation at ÜberConf comparing the two. In April, we proposed the talk to Jay Zimmerman, got accepted and went to work.

How we did it
In the beginning of May, we met at a brewery in LoDo and sketched out the app we wanted to build. We also came up with a schedule for development and a plan for the presentation. We decided to build two different webapps, each with little-to-no Ajax functionality and a few features that we could use to load test and compare the applications.

We started out with the name “Happy Trails” since we both liked trails and happy hours. Later, James found that www.ubertracks.com was available and purchased the domain. We setup the Grails app to be on bike.ubertracks.com and Play/Java to be on hike.ubertracks.com. We managed our source code on GitHub, continuously tested on CloudBees and deployed to Heroku. Two weeks ago, when we were finishing up our apps, we hired a friend (Linsay Shirley) to do QA.

After fixing bugs, I emailed Patrick Lightbody, got some “cloud dollars” for Neustar Web Performance and started running load tests. The Wednesday before last, at 2 in the morning, I recorded a simple browsing regions and routes script and set it to go to 50 users over a 5 minute period and then sustain 50 for another 5 minutes. It was fun to watch the log messages whiz through my console so fast they got blurry. About halfway through testing the Grails app, there was an OOM issue, but it eventually recovered. Limiting db connections to 4 and scaling to 5 Dynos in future tests helped alleviate any issues.

We took our development experience, the load/performance testing data, and a bunch of ecosystem stats and built our smackdown presentation. We used reveal.js, GitHub Files and Google Charts to make things more dynamic.

What we found
We arrived at a number of conclusions after doing our research:

Code

  • From a code perspective, Play 2 and Grails 2 are very similar frameworks.
  • Code authoring was good in both, but lacking IDE support for Play 2's Scala Templates.
  • Grails Plugin Ecosystem is excellent.
  • TDD-Style Development is easy with both.
  • Type-safety in Play 2 was really useful, especially routes.

Statistical Analysis

  • Grails has better support for FEO (YSlow, PageSpeed)
  • Grails has less LOC! (6 lines less, but 40% more files)
  • 1 Dyno - Grails had 2x transactions!
    • Grails experienced OOM about halfway through.
  • Apache Benchmark with 10K requests:
    • Play: ~10% failed requests, Grails: 0
    • Requests per second: {Play: 170, Grails: 198}
    • Requests per second: {Play: 251, Grails: 198}
  • Load Test with 100 Real Users:
    • Grails: 10% more transactions, 0 errors

Ecosystem Analysis

  • "Play" is difficult to search for.
  • Grails is more mature.
  • Play has momentum issues.
  • LinkedIn: more people know Grails than Spring MVC.
  • Play has 3x user mailing list traffic.
  • We had similar experiences with documentation and questions.
  • Outdated documentation is a problem for both.
  • Play has way more hype!

We figured we spent around 100 hours developing the apps, gathering data and creating the presentation. The good news is it's all open source! This means you can clone the project on GitHub (Grails is in the grails2 branch, Play is in the play2_java branch) and help us improve it. The presentation is in the master branch in the preso directory.

All the data we gathered is open for debate and we’d love to tune our apps to handle more requests per second. In fact, we already had a contributor discover an issue and provide a fix for Play that increases its throughput from 170 req/second to 252 req/second!

Regardless of what the stats and pretty graphs say, we both enjoyed our experiences with Play 2 and Grails 2. If you haven't tried them yourself, we encourage you to do so.

Posted in Java at Jun 25 2012, 07:10:57 AM MDT 19 Comments

Migrating to Play 2 and My ÜberConf Presentation

In my last post about migrating to Play 2, I said I'd write another post on the rest of my experience. While I'm not completely finished with migrating to Play 2, I feel like I've done enough to talk about the issues I encountered.

Validation and Displaying Errors
With Play 1, I can't help but think validation was a bit more intuitive. For example, here's how I populated an object from request parameters, converted a value and validated its data was fit to put in a database.

var workout = params.get("workout", classOf[Workout])

// change duration to time
var duration = params.get("workout.duration")
workout.duration = convertWatchToTime(duration)

Validation.valid("workout", workout)

if (Validation.hasErrors) {
  renderArgs.put("template", "Profile/edit")
  edit(id);
  ...
} else { // put into db

With Play Scala 2, you have to define a Form structure and bind it from the request. Based on what I was able to conjure up, I ended up writing the following code to accomplish the same thing:

val workoutForm = Form(
  mapping(
    "id" -> ignored(NotAssigned: anorm.Pk[Long]),
    "title" -> text,
    "description" -> text,
    "duration" -> nonEmptyText,
    "distance" -> nonEmptyText,
    "postedAt" -> optional(date),
    "athleteId" -> optional(longNumber)
  )((id, title, description, duration, distance, postedAt, athleteId) =>
    Workout(id, title, description, convertWatchToTime(duration), distance.toDouble, null, 0))
    ((w: Workout) =>
      Some((w.id, w.title, w.description, w.duration.toString, w.distance.toString, null, Some(0))))
)
...
workoutForm.bindFromRequest.fold(
  form => {
    Ok(Scalate("/Profile/edit.jade").render(request, 'errors -> form.errors))
  },
  workout => { // put into db

First of all, the Play 2 version is quite a bit more verbose, but most of that comes from the re-defining of my model object as a form. It seems strange that the Java API allows you to do it in one line whereas the Scala version does not. Also, I was unable to figure out how to get the data from my "form" back into the request so I could refill input fields. I'll admit, I didn't spend a lot of time trying to figure it out, but it did fail the 10 minute test. Note to self: use HTML5's required attribute to reduce the need for server-side validation on modern browsers.

On a more positive note, I did like the way I was able to use routes in my Jade templates. It was as simple as importing the routes class and using it as you would in Play's Scala Templates:

-import controllers._

form(method="post" class="form-stacked" id="workoutForm"
  action={routes.Profile.postWorkout(workout.map(_.id.get))})
  input(type="hidden" name="id" value="#{workout.map(_.id)}")

Secure Social
After getting most of my UI working, I started looking at the Secure Social Module for Play 2. Below are the steps I had to go through to install it:

  1. Cloned GitHub project to my hard drive.
  2. Copied module-code/* into my projects' modules/securesocial directory.
  3. Modified project/Build.scala to add secureSocial and dependsOn to my project.
    val secureSocial = PlayProject(
      appName + "-securesocial", appVersion, mainLang = SCALA, path = file("modules/securesocial")
    )
    
    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      // Add your own project settings here
    ).dependsOn(secureSocial).aggregate(secureSocial)
    
  4. Added a conf/securesocial.conf and included it in my application.conf with the following line:
    include "securesocial.conf"
    
  5. Added a conf/play.plugins with the following to get Twitter to load as a provider:
    10000:securesocial.core.providers.TwitterProvider
    
  6. Created an InMemoryUserService.scala and referenced it in my play.plugins file:
    9999:services.InMemoryUserService
    
  7. Added Secure Social's routes to my conf/routes file.

Once I'd finished all these steps, I fired up my app and was pleasantly surprised to find I could navigate to /login and successfully authenticate via Twitter. Installing Secure Social in a Play 2 app is quite a bit harder than adding it as a dependency in Play 1, but I was thankful that I got it to work in under 10 minutes.

Heroku
The next thing I did was attempt to deploy my app to Heroku. I knew there might be some issues with Scalate after reading Jan Helwich's blog post about Scalate on Heroku. The first things I encountered were 1) a successful startup and 2) an error in my browser.

Action not found

I was able to reproduce this issue locally by running "play clean stage" and starting the app with "target/start". After 30 minutes of banging my head against the wall, I guessed it might be caused by Secure Social. Removing Secure Social solved the problem and I was back in business. However, this time when I deployed, I received the error that Jan had mentioned might happen.

2012-06-21T07:07:12+00:00 app[web.1]: [error] o.f.s.l.DefaultLayoutStrategy - Unhandled: org.fusesource.scalate.TemplateException: target/../tmp/src/app/target/../app/views/layouts/default.jade.scala (No such file or directory)
2012-06-21T07:07:12+00:00 app[web.1]: [error] application - 
2012-06-21T07:07:12+00:00 app[web.1]: 
2012-06-21T07:07:12+00:00 app[web.1]: ! @6amfgf02h - Internal server error, for request [GET /] ->
2012-06-21T07:07:12+00:00 app[web.1]: 
2012-06-21T07:07:12+00:00 app[web.1]: play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[TemplateException: target/../tmp/src/app/target/../app/views/layouts/default.jade.scala (No such file or directory)]]
2012-06-21T07:07:12+00:00 app[web.1]:   at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]:   at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]:   at akka.actor.Actor$class.apply(Actor.scala:311) [akka-actor-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]:   at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]:   at akka.actor.ActorCell.invoke(ActorCell.scala:619) [akka-actor-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]:   at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:196) [akka-actor-2.0.1.jar:2.0.1]
2012-06-21T07:07:12+00:00 app[web.1]: Caused by: org.fusesource.scalate.TemplateException: target/../tmp/src/app/target/../app/views/layouts/default.jade.scala (No such file or directory)
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.compileAndLoad(TemplateEngine.scala:834) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.compileAndLoadEntry(TemplateEngine.scala:691) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.liftedTree1$1(TemplateEngine.scala:411) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.load(TemplateEngine.scala:405) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.load(TemplateEngine.scala:475) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.layout.DefaultLayoutStrategy.org$fusesource$scalate$layout$DefaultLayoutStrategy$$tryLayout(DefaultLayoutStrategy.scala:77) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]: Caused by: java.io.FileNotFoundException: target/../tmp/src/app/target/../app/views/layouts/default.jade.scala (No such file or directory)
2012-06-21T07:07:12+00:00 app[web.1]:   at java.io.FileOutputStream.open(Native Method) ~[na:1.6.0_20]
2012-06-21T07:07:12+00:00 app[web.1]:   at java.io.FileOutputStream.(FileOutputStream.java:209) ~[na:1.6.0_20]
2012-06-21T07:07:12+00:00 app[web.1]:   at java.io.FileOutputStream.(FileOutputStream.java:160) ~[na:1.6.0_20]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.util.IOUtil$.writeBinaryFile(IOUtil.scala:111) ~[scalate-util-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.compileAndLoad(TemplateEngine.scala:747) ~[scalate-core-1.5.3.jar:1.5.3]
2012-06-21T07:07:12+00:00 app[web.1]:   at org.fusesource.scalate.TemplateEngine.compileAndLoadEntry(TemplateEngine.scala:691) ~[scalate-core-1.5.3.jar:1.5.3]

I tried his suggestion (removing the first slash on my Scalate paths) but it didn't work. I tried adding in Scalate pre-compilation, but that didn't solve the problem either. The good news is I did solve it this afternoon by changing my Scalate object to use a canonical path instead of an absolute one.

iPhone App
In addition to the changes mentioned here, I re-wrote the iPhone app for Play More. I upgraded it to PhoneGap 1.8.1, used jQTouch, developed with AppCode (instead of Xcode) and had a pretty good experience. The only issue I ran into was with the jqt.bars extension from DataZombies. I briefly tried to integrate it and then decided not to. However, I left all its JS and CSS in my page and this caused scrolling to not work and made the app sluggish. Removing the files solved the problem. The other big improvement I made was moving all the static assets (JS, CSS, images) into the mobile app instead of referencing them from http://play-more.com. This reduced the startup time from 30-40 seconds to 3-4 seconds!

Presentation and Source Code
I presented all of these findings and told my story at ÜberConf this morning. In addition, I announced that the code is now open source and available on GitHub. You can view my presentation below or on Slideshare.

Conclusion
Would I do it again? Learning Scala was my primary motivator for digging into Play. When Play 2 was announced, I thought migrating my app to the new version would be easy. Unfortunately, the Play Developers decided to break backwards-compatibility and wrote a whole new framework that still seems to be in its infancy. I think you can see from my last couple of posts that migrating from Play 1.x to 2.x was not an easy task. It's been nice to learn more about Play and Scala in the process, but living on the bleeding edge was also quite frustrating at times. Play Scala 1.x seemed to be quite a bit more productive than Play 2, especially because of the Magic[T] in Anorm, but also because it required less code in Controllers.

I found Anorm and Scalate to be huge time sinks and don't know if I'd recommend using either one in a Play 2 project. I'm sure Scalate will be easier to use as its Play 2 integration gets more refined, but I don't know if there's any hope for a JDBC abstraction that doesn't produce error messages when things go south.

On the upside, my experience with HTML5 and CoffeeScript was wonderful. They did what I asked them to do and didn't cause much pain. When a browser-based webapp couldn't handle geo running in the background, PhoneGap came to the rescue.

I plan on continuing to develop Play More! If you'd like to help, checkout the open issues and viva la open source!

Posted in Java at Jun 21 2012, 04:09:22 PM MDT 1 Comment