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,226 entries found.

You can also try this same search on Google.

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

Upgrading to Play 2: Anorm and Testing

This time last year, I decided I wanted to learn Scala. I chose the Play Framework as my vehicle for learning and I added CoffeeScript and Jade to the mix. I packaged it all up, learned a bunch and presented it at Devoxx 2011.

In January, I added SecureSocial, JSON Services and worked a bit on the mobile client. I presented my findings at Jfokus shortly after. As part of my aforementioned post, I wrote:

Right before we left for Jfokus, I was able to get everything to work, but didn't spend as much time as I'd like working on the mobile client. If this talk gets accepted for Devoxx France, I plan on spending most of my time enhancing the mobile client.

I had some complications (a.k.a. too much vacation) with Devoxx France and wasn't able to attend. To make up for it, I submitted the talk to ÜberConf. It got accepted and I started working on my app a couple weeks ago. So far, I've spent about 8 hours upgrading it to Play 2 and I hope to start re-writing the mobile client later this week. I plan on using Cordova, jQTouch and releasing it in the App Store sometime this month.

Upgrading to Play 2
When I heard about Play 2, I thought it was a great thing. The developers were re-writing the framework to use Scala at the core and I was already using Scala in my app. Then I learned they were going to throw backwards compatibility out the window and I groaned. "Really? Another web framework (like Tapestry of old) screwing its users and making them learn everything again?!", I thought. "Maybe they should call it Run instead of Play, leaving the old framework that everyone loves intact."

However, after hearing about it at Devoxx and Jfokus, I figured I should at least try to migrate. I downloaded Play 2.0.1, created a new project and went to work.

The first thing I learned about upgrading from Play 1.x to Play 2.x is there's no such thing. It's like saying you upgraded from Struts 1 to Struts 2 or Tapestry 4 to Tapestry 5. It's a migration, with a whole new project.

Evolutions
I started by looking around to see if anyone had documented a similar migration. I found two very useful resources right off the bat:

From Jan's Blog, I learned to copy my evolutions from my Play 1.x project into conf/evolutions/default. I changed my application.conf to use PostgreSQL and wrote an EvolutionsTest.scala to verify creating the tables worked.

import org.specs2.mutable._

import play.api.db.DB
import play.api.Play.current

import anorm._

import play.api.test._
import play.api.test.Helpers._

class EvolutionsTest extends Specification {

  "Evolutions" should {
    "be applied without errors" in {
      evolutionFor("default")
      running(FakeApplication()) {
        DB.withConnection {
          implicit connection =>
            SQL("select count(1) from athlete").execute()
            SQL("select count(1) from workout").execute()
            SQL("select count(1) from comment").execute()
        }
      }
      success
    }
  }
}

Then I began looking for how to load seed data with Play 2.x. In Play 1.x, you could use a BootStrap job that would load sample data with YAML.

import play.jobs._
import play.Play

@OnApplicationStart
class BootStrap extends Job {

  override def doJob() {

    import models._
    import play.test._

    // Import initial data if the database is empty
    if (Athlete.count().single() == 0) {
      Yaml[List[Any]]("initial-data.yml").foreach {
        _ match {
          case a: Athlete => Athlete.create(a)
          case w: Workout => Workout.create(w)
          case c: Comment => Comment.create(c)
        }
      }
    }
  }
}

This is no longer a recommended practice in Play 2. Instead, they recommend you turn your YAML into code. 10 minutes later, I had a Global.scala that loaded seed data.

import models._
import play.api._
import play.api.Play.current

import anorm._

object Global extends GlobalSettings {

  override def onStart(app: Application) {
    InitialData.insert()
  }
}

/**
 * Initial set of data to be loaded
 */
object InitialData {

  def date(str: String) = new java.text.SimpleDateFormat("yyyy-MM-dd").parse(str)

  def insert() {

    if (Athlete.count() == 0) {

      Seq(
        Athlete(Id(1), "[email protected]", "beer", "Matt", "Raible"),
        Athlete(Id(2), "[email protected]", "whiskey", "Trish", "McGinity")
      ).foreach(Athlete.create)

      Seq(
        Workout(Id(1), "Chainsaw Trail",
          """
            A beautiful fall ride: cool breezes, awesome views and yellow leaves.

            Would do it again in a heartbeat.
          """, 7, 90, date("2011-10-13"), 1),
        Workout(Id(2), "Monarch Lake Trail",
          "Awesome morning ride through falling yellow leaves and cool fall breezes.",
          4, 90, date("2011-10-15"), 1),
        Workout(Id(3), "Creekside to Flume to Chainsaw",
          "Awesome morning ride through falling yellow leaves and cool fall breezes.",
          12, 150, date("2011-10-16"), 2)
      ).foreach(Workout.create)

      Seq(
        Comment(1, "Jim", "Nice day for it!"),
        Comment(2, "Joe", "Love that trail."),
        Comment(2, "Jack", "Where there any kittens there?")
      ).foreach(Comment.create)
    }
  }
}

Anorm's Missing Magic
Before starting with Play 2, I knew it had lost some of its magic. After all, the developers had mentioned they wanted to get ride of the magic and moving to Scala allowed them to do that. However, I didn't think I'd miss Magic[T] as much as I do. Like Martin Fowler, I like ORMs and having to use SQL again seems painful. It seems like a strange shift for Play to reduce type-safety on the backend, but increase it in its templates. Oh well, to each their own. I may eventually move to Squery, but I wanted to do a side-by-side comparison as part of my migration.

Using the aforementioned tutorial from James and Jan's blog posts, as well as Guillaume's Play 2.0/Anorm, I set about creating new model objects. I wrote a bunch of SQL, typed up some new finders and migrated my tests from ScalaTest to the new default, specs2. The Mosh Pit's Migrating a Play 1.2 website to Play 2.0 was a great help in migrating tests.

That's when I started having issues with Anorm and figuring out how its parser syntax works. After struggling for a few days, I finally found yabe-play20-scala. Since I'd used the yabe tutorial from Play 1.x, it was familiar and helped me get past my problems. Now, things aren't perfect (Workouts aren't ordered by their posted date), but everything compiles and tests pass.

To illustrate how little code was required for Anorm 1.x, checkout Workout.scala in Play 1.x vs. Play 2.x. The Play 1.x version is 66 lines; Play 2.x requires 193 lines. I don't know about you, but I kinda like a little magic in my frameworks to reduce the amount of code I have to maintain.

I was pleasantly surprised by specs2. First of all, it was an easy migration from ScalaTest. Secondly, Play's FakeApplication made it very easy to write unit tests. The line count on my UnitTests.scala in Play 1.x vs. Play 2.x is almost identical.

Summary
The first few hours of developing with Play 2 were frustrating, mostly because I felt like I had to learn everything over again. However, I was pleased to find good references on migrating from Play 1.x. Last night, I migrated all my Controllers, integrated Scalate and got most of my views rendering. I still have issues rendering validation errors, but I hope to figure that out soon. The last 2 hours have been much more fun and I feel like my Scala skills are coming along. I think if the Play Team could eliminate those first few hours of struggling (and provide almost instant joy like Play 1.x) they'd really be onto something.

As soon as I figure out how to validation and how to add a body class based on the URL, I'll write another post on the rest of my migration. A Play 2-compatible version of SecureSocial just came out this evening, so I may integrate that as well. In the meantime, I'll be working on the iPhone app and finishing up a Grails 2 application for James Ward and my Grails vs. Play Smackdown.

Posted in Java at Jun 05 2012, 08:55:40 PM MDT 7 Comments