Matt RaibleMatt Raible is a Web Developer and Java Champion. 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,223 entries found.

You can also try this same search on Google.

A Spectacular Trip to Stockholm and Madrid

When I travel in the winter, it's usually to ski resorts or client sites, not to conferences. However, when the Mattias Karlsson invited me to speak at Jfokus, I jumped at the opportunity. That same day in Antwerp, Sergi Almar asked me to speak at Spring I/O. Turns out, both conferences were in the same week so we worked out the logistics of traveling to Stockholm and Madrid and got ready for a spectacular trip.

Trish and I started our journey two weeks ago by flying over the top of world, connecting through Seattle and Reykjavik (Iceland) before arriving in Stockholm on Monday afternoon. We took the bullet train from the airport to downtown and walked a couple blocks to the conference venue/hotel. We checked in, relaxed, then met a bunch of folks a few hours later to go to the speaker's dinner at F12.

James Ward and Enno Runne by Trish McGinity Juergen Hoeller Speakers Dinner Singers Matt Raible James Ward Rickard Oberg Jfokus speakers dinner

On Tuesday, I attended quite a few sessions at the conference, took and nap and delivered my Comparing JVM Web Frameworks talk at 17:00. The Atlassian Bar opened after my talk concluded and we enjoyed some tasty beverages while talking tech with new and old friends. James Ward's Cloud BOF started at 8 and we enjoyed the beer and banter before heading out to the local Sports Bar. We scared the bar's proprietors with our hunger and thirst at such a late hour, but they served us anyway.

John Wilander Jfokus 2012 Thanks for the beer Atlassian! Cloud Conversations Heroku James Ward After BOF Dinner Crew

On Wednesday, I got woken up by the hotel's housekeeping at 9:52 and I had to be on stage at 10:10. I got dressed and downstairs as fast as I could and put the final touches on my presentation as people were filing in the room. I opened my talk with, "You ever had one of those morning where the housekeeping woke you up and you had to be on stage 10 minutes later?"

The conference ended that day, but Trish and I extended it a bit by going to the Scala Stockholm Meetup and walking around the city to capture some night photos. I wrote up a blog post about my presentations and Jfokus the next morning and Trish posted both her Jfokus and Stockholm pictures to Flickr. Below are some of my favorite pictures of Sweden.

Stockholm bike along rail

Storkyrkan Saint Nicolaus Church Stockholm Stockholm Town Hall
Stockholm Evening
Stockholm Lion
Riddenholm Church
Stockholm View

On Thursday, we traveled to Madrid for Spring I/O. We arrived at sunset and met up with Josh Long and his Dad for a ride to our hotel. Trish went to high school in Puerto Rico and got to show of her Spanish skills when she helped the driver find the hotel. I spoke on Friday morning and we spent the rest of the weekend taking photos and enjoying Carnival. We had a great hotel in the heart of Madrid and could walk to almost all the historic sites.

It was great seeing Trish in Madrid. Her Spanish was excellent and I felt like I had a personal tour guide the whole time. Her pictures show the weather was beautiful and the sites, amazing.

Templo de Debod

Iglesia San Gines Palace Real

Plaza Mayor Madrid Evening Commute Puerta de Alcala Madrid

Almudena Cathedral

You can see all of Trish's Madrid photos on Flickr. I also published mine in a Stockholm and Madrid 2012 album.

Yes, it was quite a bit of work preparing for two conferences in one week. However, both were in exotic, beautiful locations. Not only that, but Mattias and Sergi did a great job of providing terrific local experiences. Thanks guys, we had a blast.

Happy Travelers in Madrid

For more of Trish's photos from our world travels, see McGinity Photo's World Gallery.

Posted in General at Feb 26 2012, 09:11:03 PM MST 2 Comments

Comparing Web Frameworks and HTML5 with Play Scala at Jfokus 2012

Riddenholm Church Stockholm seems a lot like Denver this time of year. Cold, snowy and beautiful. Trish and I arrived in Stockholm (Sweden) on Monday for the Jfokus conference and we're traveling to Madrid today for the Spring I/O conference. I was invited to Jfokus within minutes of delivering my HTML5 with Play Scala talk at Devoxx.

Both the Jfokus and Spring I/O Organizers were interested in my Comparing JVM Web Frameworks talk, so I updated it to reflect my latest thoughts. First of all, I mentioned that there's a lot of great frameworks out there and I think the reason people are so apprehensive to choose one is because they've chosen badly at one point. This might've been Struts back in the day (even thought it was one of the best frameworks at the time) or it might be because a vendor talked them into it. However, if you look at the modern JVM frameworks today, you should be able to see that they're all pretty awesome.

I mentioned how I think Web developers should know JavaScript and CSS. If you're a Java developer and you call yourself a web developer, you're letting your framework do too much of the work for you. I mentioned Rich Manalang's Modern Principles in Web Development, where he talks about his core web development principles.

  • Designing for mobile first (even if you’re not building a mobile app)
  • Build only single page apps
  • Create and use your own REST API
  • “Sex sells” applies to web apps

I've found these principles to be true in my own experience and suggested that if you want to be a web developer, the frameworks you might want to learn are not traditional JVM web frameworks, but rather client-side MVC frameworks. For those Java developers that don't want to be web developers, I suggest they strengthen their services development knowledge by reading Hot to GET a Cup of Coffee.

You can see my updated presentation below, on Slideshare or as a downloadable PDF. You can also watch the video.

I delivered my 2nd presentation on HTML5 with Play Scala, CoffeeScript and Jade on Wednesday morning. This talk is one of my favorites and I prepared for it over the last several weeks by adding JSON CRUD Services and SecureSocial to my HTML5 Fitness Tracking application. 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. After my latest experience developing, I can see how Rich's first principle (above) makes a lot of sense.

Below is my presentation for this talk. Of course, it's on Slideshare and downloadable as a PDF.

I also updated the Developing Play More demo video to show my latest efforts.

Delivering these talks at Jfokus was a lot of fun. Yes, it was a lot of work and stress to prepare them. However, I also learned a lot creating them and I hope the audience benefitted from that.

Jfokus 2012 The conference itself was incredible. I got to meet Peter Hilton and Helena Hjertén as I was registering. The speaker's dinner at F12 was off-the-hook good and I had the pleasure of finally meeting Rickard Öberg.

I also attended some fantastic presentations, including Peter Hilton's Play Framework 2.0, Bodil Stokke's CoffeeScript: JavaScript without the Fail, Pamela Fox's Client-side Storage and Heiko Seeberger's Scala in Action. I don't know if Heiko has published any slides, but I'm guessing not since most of his presentation was live coding.

I have lots of good memories from Jfokus. Many thanks to Mattias for inviting me!

Posted in Java at Feb 16 2012, 12:01:05 AM MST 5 Comments

Secure JSON Services with Play Scala and SecureSocial

AntwerpTownSquare Last November, I traveled to Antwerp to speak at Devoxx. After my talk on HTML5 with Play Scala, Mattias Karlsson approached me and we had a chat about doing the same talk at Jfokus in Stockholm. I agreed and we began talking details after Trish and I returned to the US.

Jfokus

I wrote this article on a plane between Denver and Seattle and will be hopping over the North Pole to Stockholm via Iceland tonight. For the past couple of weeks, I've been updating my Play More! HTML5/mobile app to add some new features. Most notably, I wanted to upgrade to Play 2.0, create JSON services and add authentication.

Upgrading to Play 2.0
My attempt to upgrade to Play 2.0 involved checking out the source from GitHub, building and installing the RC1 snapshot. As I tried to upgrade my app and started getting failed imports, I turned to the internet (specifically StackOverflow) to see if it was a good idea. The first answer for that question suggested I stay with 1.x.

If it's a critical project, to be finished before next March 2012, I would go with Play 1.x. If it's a less important project, which could be delayed, and that in any case won't be released before March 2012, try Play 2.0.

While I didn't plan on releasing Play More! before Jfokus, I decided upgrading didn't add a whole lot to the talk. Also, I couldn't find a Play Scala 0.9.1 to Play 2.0 upgrade guide and I didn't have enough time to create one. So I decided to stick with Play 1.2.4 and add some JSON services for my iPhone client.

JSON Servers
I found Manuel Bernhardt's Play! Scala and JSON. This led me to Jerkson, built by the now infamous @coda. I was able to easily get things working fairly quickly and wrote the following WorkoutService.scala:

package controllers.api

import play.mvc.Controller
import models._
import com.codahale.jerkson.Json._

object WorkoutService extends Controller {

  def workouts = {
    response.setContentTypeIfNotSet("application/json")
    generate(Workout.find().list())
  }
  def edit(id: Long) = {
    generate(Workout.byIdWithAthleteAndComments(id))
  }

  def create() = {
    var workout = params.get("workout", classOf[Workout])
    Workout.create(workout)
  }

  def save(id: Option[Long]) = {
    var workout = params.get("workout", classOf[Workout])
    Workout.update(workout)
  }

  def delete(id: Long) = {
    Workout.delete("id={id}").on("id" -> id).executeUpdate()
  }
}

Next, I added routes for my new API to conf/routes:

GET     /api/workouts               api.WorkoutService.workouts
GET     /api/workout/{id}           api.WorkoutService.edit
POST    /api/workout                api.WorkoutService.create
PUT     /api/workout/{id}           api.WorkoutService.save
DELETE  /api/workout/{id}           api.WorkoutService.delete

Then I created an ApiTest.scala class that verifies the first method works as expected.

import play.test.FunctionalTest
import play.test.FunctionalTest._
import org.junit._

class ApiTests extends FunctionalTest {
  
    @Test
    def testGetWorkouts() {
        var response = GET("/api/workouts");
        assertStatus(200, response);
        assertContentType("application/json", response)
        println(response.out)
    }
}

I ran "play test", opened my browser to http://localhost:9000/@tests and clicked ApiTests -> Start to verify it worked. All the green made me happy.

Play More API Tests

Finally, I wrote some CoffeeScript and jQuery to allow users to delete workouts and make sure delete functionality worked.

$('#delete').click ->
  $.ajax
    type: 'POST'
    url: $(this).attr('rel')
    error: ->
      alert('Delete failed, please try again.')
    success: (data) ->
      location.href = "/more"

I was very impressed with how easy Play made it to create JSON services and I smiled as my CoffeeScript skills got a refresher.

The Friday before we left for Devoxx, I saw the module registration request for SecureSocial.

SecureSocial with Play Scala
From SecureSocial's README:

SecureSocial allows you to add an authentication UI to your app that works with services based on OAuth1, OAuth2, OpenID and OpenID+OAuth hybrid protocols.

It also provides a Username and Password mechanism for users that do not wish to use existing accounts in other networks.

The following services are supported in this release:

  • Twitter (OAuth1)
  • Facebook (OAuth2)
  • Google (OpenID + OAuth Hybrid)
  • Yahoo (OpenID + OAuth Hybrid)
  • LinkedIn (OAuth1)
  • Foursquare (OAuth2)
  • MyOpenID (OpenID)
  • Wordpress (OpenID)
  • Username and Password

In other words, it sounded like a dream come true and I resolved to try it once I found the time. That time found me last Monday evening and I sent a direct message to @jaliss (the module's author) via Twitter.

Does Secure Social work with Play Scala? I'd like to use it in my Play More! project.

Jorge responded 16 minutes later saying that he hadn't used Play Scala and he'd need to do some research. At 8 o'clock that night (1.5 hours after my original DM), Jorge had a sample working and emailed it to me. 10 minutes later I was adding a Secure trait to my project.

package controllers

import play.mvc._
import controllers.securesocial.SecureSocial

/*
 * @author Jorge Aliss <[email protected]> of Secure Social fame.
 */
trait Secure {
  self: Controller =>

  @Before def checkAccess() {
    SecureSocial.DeadboltHelper.beforeRoleCheck()
  }

  def currentUser = {
    SecureSocial.getCurrentUser
  }
}

I configured Twitter and Username + Password as my providers by adding the following to conf/application.conf.

securesocial.providers=twitter,userpass

I also had to configure a number of securesocial.twitter.* properties. Next, I made sure my routes were aware of SecureSocial by adding the following to the top of conf/routes:

  *       /auth               module:securesocial

Then I specified it as a dependency in conf/dependencies.yml and ran "play deps".

    - play -> securesocial 0.2.4

After adding "with Secure" to my Profile.scala controller, I tried to access its route and was prompted to login. Right off the bat, I was shown an error about a missing jQuery 1.5.2 file in my "javascripts" folder, so I added it and rejoiced when I was presented with a login screen. I had to add the app on Twitter to use its OAuth servers, but I was pumped when both username/password authentication worked (complete with signup!) as well as Twitter.

The only issue I ran into with SecureSocial was that it didn't find the default implementation of SecureSocial's UserService.Service when running in prod mode. I was able to workaround this by adding a SecureService.scala implementation to my project and coding it to talk to my Athlete model. I didn't bother to hook in creating a new user when they logged in from Twitter, but that's something I'll want to do in the future. I was also pleased to find out customizing SecureSocial's views was a breeze. I simply copied them from the module into my app's views and voila!

package services

import play.db.anorm.NotAssigned
import play.libs.Codec
import collection.mutable.{SynchronizedMap, HashMap}
import models.Athlete
import securesocial.provider.{ProviderType, UserService, SocialUser, UserId}

class SecureService extends UserService.Service {
  val activations = new HashMap[String, SocialUser] with SynchronizedMap[String, SocialUser]

  def find(userId: UserId): SocialUser = {
    val user = Athlete.find("email={email}").on("email" -> userId.id).first()

    user match {
      case Some(user) => {
        val socialUser = new SocialUser
        socialUser.id = userId
        socialUser.displayName = user.firstName
        socialUser.email = user.email
        socialUser.isEmailVerified = true
        socialUser.password = user.password
        socialUser
      }
      case None => {
        if (!userId.provider.eq(ProviderType.userpass)) {
          var socialUser = new SocialUser
          socialUser.id = userId
          socialUser
        } else {
          null
        }
      }
    }
  }

  def save(user: SocialUser) {
    if (find(user.id) == null) {
      val firstName = user.displayName
      val lastName = user.displayName
      Athlete.create(Athlete(NotAssigned, user.email, user.password, firstName, lastName))
    }
  }

  def createActivation(user: SocialUser): String = {
    val uuid: String = Codec.UUID()
    activations.put(uuid, user)
    uuid
  }

  def activate(uuid: String): Boolean = {
    val user: SocialUser = activations.get(uuid).asInstanceOf[SocialUser]
    var result = false

    if (user != null) {
      user.isEmailVerified = true
      save(user)
      activations.remove(uuid)
      result = true
    }

    result
  }

  def deletePendingActivations() {
    activations.clear()
  }
}

Jorge was a great help in getting my authentication needs met and he even wrote a BasicAuth.scala trait to implement Basic Authentication on my JSON services.

package controllers

import _root_.securesocial.provider.{UserService, ProviderType, UserId}
import play._
import play.mvc._
import play.libs.Crypto

import controllers.securesocial.SecureSocial

/*
 * @author Jorge Aliss <[email protected]> of Secure Social fame.
 */
trait BasicAuth {
  self: Controller =>

  @Before def checkAccess = {
    if (currentUser != null) {
      // this allows SecureSocial.getCurrentUser() to work.
      renderArgs.put("user", currentUser)
      Continue
    }

    val realm =
      Play.configuration.getProperty("securesocial.basicAuth.realm", "Unauthorized")

    if (request.user == null || request.password == null) {
      Unauthorized(realm)
    } else {
      val userId = new UserId
      userId.id = request.user
      userId.provider = ProviderType.userpass
      val user = UserService.find(userId)

      if (user == null ||
        !Crypto.passwordHash(request.password).equals(user.password)) {
        Unauthorized(realm)
      } else {
        // this allows SecureSocial.getCurrentUser() to work.
        renderArgs.put("user", user)
        Continue
      }
    }
  }

  def currentUser = {
    SecureSocial.getCurrentUser()
  }
}

Summary
My latest pass at developing with Scala and leveraging Play to build my app was a lot of fun. While there were issues with class reloading every-so-often and Scala versions with Scalate, I was able to add the features I wanted. I wasn't able to upgrade to Play 2.0, but I didn't try that hard and figured it's best to wait until its upgrade guide has been published.

I'm excited to describe my latest experience to the developers at Jfokus this week. In addition, the conference has talks on Play 2.0, CoffeeScript, HTML5, Scala and Scalate. I hope to attend many of these and learn some new tricks to improve my skills and my app.

Update: The Delving developers have written an article on Migration to Play 2. While it doesn't provide specific details on what they needed to change, it does have good information on how long it took and things to watch for.

Posted in Java at Feb 12 2012, 04:02:43 PM MST 4 Comments

Refreshing AppFuse's UI with Twitter Bootstrap

The last time AppFuse had an update done to its look and feel was in way back in 2006. I've done a lot of consulting since then, which has included a fair bit of page speed optimization, HTML5 development and integrating smarter CSS. It was way back in '05 when we first started looking at adding a CSS Framework to AppFuse. It was Mike Stenhouse's CSS Framework that provided the inspiration and my CSS Framework Design Contest that provided its current themes (puzzlewithstyle, andreas01 and simplicity).

Since then, a lot of CSS Frameworks have been invented, including Blueprint in 2007 and Compass in 2008. However, neither has taken the world by storm like Twitter Bootstrap. From Building Twitter Bootstrap:

A year-and-a-half ago, a small group of Twitter employees set out to improve our team’s internal analytical and administrative tools. After some early meetings around this one product, we set out with a higher ambition to create a toolkit for anyone to use within Twitter, and beyond. Thus, we set out to build a system that would help folks like us build new projects on top of it, and Bootstrap was conceived.
...
Today, it has grown to include dozens of components and has become the most popular project on GitHub with more than 13,000 watchers and 2,000 forks.

The fact that Bootstrap has become the most popular project on GitHub says a lot. For AppFuse.next, I'd like to integrate a lot of my learnings over the past few years, as well as support HTML5 and modern browsers as best we can. This means page speed optimizations, getting rid of Prototype and Scriptaculous in favor of jQuery, adding wro4j for resource optimization and integrating HTML5 Boilerplate. I've used Twitter Bootstrap for my Play More! app, as well as some recent client projects. Its excellent documentation has made it easy to use and I love the way you can simply add classes to elements to make them transform into something beautiful.

Last week, I spent a couple late nights integrating Twitter Bootstrap 2.0 into the Struts 2 and Spring MVC versions of AppFuse. The layout was pretty straightforward thanks to Scaffolding. Creating the Struts Menu Velocity template to produce dropdowns wasn't too difficult. I added class="table table-condensed" to the list screen tables, class="well form-horizontal" to forms and class="btn primary" to buttons.

I also added validation errors with the "help-inline" class. This is also where things got tricky with Struts and Spring MVC. For the form elements in Bootstrap, they recommend you use a "control-group" element that contains your label and a "controls" element. The control contains the input/select/textarea and also the error message if there is one. Here's a sample element waiting for data:

<div class="control-group">
    <label for="name" class="control-label">Name</label>
    <div class="controls">
        <input type="text" id="name" name="name">
    </div>
</div>

Below is what that element should look like to display a validation error:

<div class="control-group error">
    <label for="name" class="control-label">Name</label>
    <div class="controls">
        <input type="text" id="name" name="name" value="">
        <span class="help-inline">Please enter your name.</span>
    </div>
</div>

You can see this markup is pretty easy, you just need to add an "error" class to control-group and span to show the error message. With Struts 2, this was pretty easy thanks to its customizable templates for its tags. All I had to do was create a "template/css_xhtml" directory in src/main/webapp and modify checkbox.ftl, controlfooter.ftl, controlheader-core.ftl and controlheader.ftl to match Bootstrap's conventions.

Spring MVC was a bit trickier. Since its tags don't have the concept of writing an entire control (label and field), I had to do a bit of finagling to get things to work. In the current implementation, Struts 2 forms have a single line for a control-group and its control-label and controls.

<s:textfield key="user.firstName" required="true"/>

With Spring MVC, it's a bit more complex:

<spring:bind path="user.firstName">
<fieldset class="control-group${(not empty status.errorMessage) ? ' error' : ''}">
</spring:bind>
    <appfuse:label styleClass="control-label" key="user.firstName"/>
    <div class="controls">
        <form:input path="firstName" id="firstName" maxlength="50"/>
        <form:errors path="firstName" cssClass="help-inline"/>
    </div>
</fieldset>

You could probably overcome this verbosity with Tag Files.

Figuring out if a control-group needed an error class before the input tag was rendered was probably the hardest part of this exercise. This was mostly due to Bootstrap's great documentation and useful examples (viewed by inspecting the markup). Below are some screenshots of the old screens and new ones.

Old UI - Login Old UI - Users Old UI - Edit Profile

New UI - Login New UI - Users New UI - Edit Profile

Check out the full set on Flickr if you'd like a closer look.

Even though I like the look of the old UI, I can't help but think a lot of the themes are designed for blogs and content sites, not webapps. The old Wufoo forms were a lot better looking though. And if you're going to develop kick-ass webapps, you need to make them look good. Bootstrap goes a long way in doing this, but it certainly doesn't replace a good UX Designer. Bootstap simply helps you get into HTML5-land, start using CSS3 and it takes the pain out of making things work cross-browser. Its fluid layouts and responsive web design seems to work great for business applications, which I'm guessing AppFuse is used for the most.

I can't thank the Bootstrap developers enough for helping me make this all look good. With Bootstrap 2 dropping this week, I can see myself using this more and more on projects. In the near future, I'll be helping integrate Bootstrap into AppFuse's Tapestry 5 and JSF versions.

What do you think of this CSS change? Do you change your CSS and layout a fair bit when starting with AppFuse archetypes? What can we do to make AppFuse apps look better out-of-the-box?

Update: I updated AppFuse to the final Bootstrap 2.0 release. Also, Johannes Geppert wrote a Struts 2 Bootstrap Plugin. I hope to integrate this into AppFuse in the near future.

Posted in Java at Jan 31 2012, 05:12:17 PM MST 10 Comments

2011 - A Year in Review

2010 was an awesome year, but 2011 rocked the house! At the end of last year, I kept my goals simple:

In 2011, I plan on doing two main things: keep rockin' it with Trish and finishing The Bus. Everything else is gravy.

As predicted, it was a spectacular year, but I only accomplished 50% of my goals. That is, Trish and I had a great time skiing (especially in Utah), moving in together, traveling the world and getting engaged in Versailles. I even satisfied some 5-year goals: building a sauna in my basement and getting a ski shack in the mountains.

However, I didn't get much done with The Bus. Or rather, the guys at MotorWorks Restorations didn't drain me for all I'm worth in 2011. We did make good progress with estimating the final cost and obtaining many hard-to-find parts though. I now have a Porsche 911 Engine (1983 3.0L 6 cylinder), a Porsche 901 5 speed transmission, Porsche "Turbo Twist" wheels and a Custom Air Ride Front Beam from Franklin's VW Works. The thing that slowed our progress the most was the custom beam, as it took almost 6 months from order to delivery. When it arrived in September, I decided to put things on hold. I didn't want to get my bus back in the midst of winter and not be able to drive it.

[Read More]

Posted in Roller at Jan 11 2012, 09:45:20 AM MST 2 Comments

Our Engaging Trip to Paris and Antwerp

If you're a technologist, you should attend the Devoxx conference at least once in your life. It's one of the finest conferences on the planet. If you're a fan of Belgian beer, you owe it to yourself to visit Belgium to savor a taste. If you're a romantic, Paris is a recommended destination. Since I'm a technologist, love Belgian beer and consider myself a romantic, I went for the trifecta a couple weeks ago on what's becoming an annual trek to Devoxx. When Trish and I traveled to Devoxx last year, we flew to Amsterdam and took the train to Antwerp. This year, we decided to fly to Paris and take the train.

Much like last year, we witnessed another Broncos over Chiefs victory the Sunday before we left. That night, I stayed up until the wee hours of the morning finishing my Devoxx presentation. We left Denver around noon and met up with James Ward at the Red Carpet Club in Chicago. While sipping cocktails and catching up, I wrote a blog post about how PhoneGap rescued me a couple days earlier.

We slept soundly on the flight over, thanks to little sleep the night before. After arriving in Paris, we took the train to the the Notre Dame de Paris and had some breakfast nearby.

Notre Dame Cathedral Paris

We were planning on exploring throughout the day, but quickly realized that hauling our bags around was no fun and headed to Gare du Nord to catch a Thalys train to Brussels. We gasped at the cost of two first-class tickets, but soon forgot when we settled into our seats with free wi-fi, Belgian beers and power. After talking a local train to Antwerp, we finished our 21-hour journey by checking into the Hilton Antwerp in the city center. We were warmly welcomed with excellent Belgian beers on ice in our room and celebrated with a delicious meal at De Godevaart.

On Wednesday, I headed to Devoxx and attended a couple of great talks: Play 2.0, A web framework for a new era and PhoneGap for Hybrid App Development. As you can imagine, both talks were extremely interesting for me since I'd been using Play for several months and was recently saved by PhoneGap. Play 2.0 Beta was announced just before the Play talk and my blog post about the Play 2.0 session was picked up by Hacker News and the hits rolled in.

That afternoon, I headed back to my hotel with James Ward and met up with Trish for a couple beers. We spent a few hours in our hotel lobby updating presentations, editing videos, editing photos and getting ready for our talks on Thursday. That evening, we enjoyed a scrumptious dinner in the dungeon-like Pelgrom and conversations with Kevin Nilson, Sadek Drobi, Guillaume Bort and David Geary. I was pleased to find out from Sadek and Guillaume that Play 2.0 will include many fast website best practices, including concatenation, minification and gzipping of static assets. We retired early to get a good night's sleep before my talk on Thursday.

Kwak Kwak Kwak! Candle at Pelgrom

Matt Raible and Crew at Devoxx dinner Matt Raible at Pelgrom

On Thursday, both Trish and I journeyed to Devoxx to watch James Ward talk about how to deploy Java, Play Framework, and Scala apps on Heroku. My talk was an hour later and I gulped as I stood up front and watched the (very large) auditorium fill up with Devoxxians. Since I'd never rehearsed my talk or timed it, I was a bit nervous. Luckily, it ended up being one of my best-timed performances and there was even time for Q and A at the end. You can imagine the smile on my face as AC/DC's Thunderstruck blasted through the speakers during my video demo. After my talk finished, it was great to see all the positive feedback on Twitter and enjoy an "Atlas Beer" while watching Java Posse Live.

James Ward speaking on Heroku at Devoxx Matt Raible speaking at Devoxx Belgium 2011

Audience at Matt Raible's Presentation Devoxx Belgium

That evening, we had dinner with the Java Posse crew and James Ward before heading to the Devoxx Party @ Noxx.

Devoxx Party @ Noxx

Yes, we had an awesome time at Devoxx. I was pleased with the positive response from my talk and learned a bunch from the few talks I attended. Thanks to Stephan for inviting me and organizing one of the best conferences I've ever attended. For our last night in Antwerp, we dined at Huis De Colvenier and especially enjoyed our aperitif in the 19th-century wine cellar.

Huis De Colvenier Huis De Colvenier Huis De Colvenier Huis De Colvenier

Riverside in Antwerp Antwerp Town Square

Mmmm, Belgium Beer... We love Belgian Beer

Paris and Beyond
This brings us to my favorite part of this story. I was pretty stressed leading up to our departure to Devoxx because I had so many deadlines. I had a deadline with my current client to finish up some features before I left, I had to finish my Devoxx presentation (and app developed for the talk) and I had a secret deadline to finish my proposal to Trish. That's right, I was planning on proposing marriage to my dream girl. I mean, we were going to the diamond capital of the world (Antwerp) and one of Earth's most romantic cities (Paris). It seemed like the perfect opportunity to ask her to marry me. We did some ring shopping before we left Denver, but she didn't realize I had purchased one before we left.

We're both big music fans, so I decided months earlier that I would propose with lines from songs we both liked. Of course, I waited until the last minute to compose my prose, but I did finish it before we left for Europe. However, with all the Devoxx shenanigans, I didn't have time to memorize my proposal. Instead, I recorded it using the "Voice Memos" on my iPhone. I did this in the wee hours of the morning on Friday, while I was watching the Broncos game on the internet.

Saturday afternoon, we traveled to Paris via Thalys and checked into our hotel around sunset. When we stepped outside an hour later, I remember saying to Trish, "the Eiffel Tower looks pretty small, I thought it'd be bigger". After walking for a bit, it turned from small to big to huge. My plan that night was to propose on the tower. As Trish snapped pictures along our walk, I was taking out the piece of paper I had the proposal printed on and trying to memorize it. As you can imagine, I had to to this stealthily and by the time we reached the Eiffel Tower, I had enough memorized to propose. We arrived around midnight and were disappointed to find it was closed. This terminated my proposal plans for that night, but we still enjoyed the sparkling tower lights and took several pictures.

The Eiffel Tower The Eiffel Tower

The next day, Sunday, we traveled to the Château de Versailles. This was a recommendation from my good friend Eric, who had recently traveled to Paris with his wife, Heather. In fact, I owe a lot to Eric. He recommended we extend our trip to Paris (he'd traveled there disgruntled about not doing a beach vacation, then fell in love with the city) and suggested a number of great locations to visit. He also recommended proposing in the Gardens of Versailles, a very romantic location according to him. I had this in the back of my mind as we did an audio tour through the Palace of Versailles. As we ventured out into the Orangerie, I started hatching a plan to get Trish down to the gardens and try to rent bikes. We both love biking and the outdoors, so I figured it'd be a nice way to spend our memorable moment. As we strolled closer and I didn't see bikes to rent, I spotted the Grand Canal and noticed they had row boats.

The Versailles Orangerie Château de Versailles Gardens of Versailles Trees in the Versailles Gardens

Bassin d’Apollon – the Apollo Fountain

When we first arrived at the boat dock, there was a long line, but it magically disappeared moments later. We stepped into the boat, rowed to the center of the canal and paused for a bit to take in the beautiful day and the setting sun. Trish asked me to row to a better spot so she could photograph the sunset, but instead I said "here, listen to this" and handed her my headphones. I pressed play and watched her face light up as she heard my voice in her ears. 90 seconds later, I asked "Trish McGinity, will you marry me?" She responded with, "Of course!" :)

Happy Versailles Sunset

The rest of our trip in Paris was quite romantic and fun. We decided to wait until we got back to The States before telling anyone we were engaged. This meant we had three days of just us, Paris and some of the most beautiful art in the world. We explored the Louvre for 5-hours on Monday, marveling at the low-rider on display near the entrance and all the famous paintings.

Trish and the Louvre At The Louvre Lowrider in the Louvre Liberty Leading the People

Louvre

We imbibed in $40 martinis at The Hemingway Bar and scarfed down some delicious pizza at Gambino's. We had breakfast at Angelina's, toured La Sainte-Chapelle, hiked up Arc de Triomphe and wandered through the shopping districts Champs-Élysées and Faubourg St-Honoré. Yes, we fell in love with Paris and can't wait to return for Devoxx France in April.

Arc de Triumph

We departed Paris on the Wednesday morning before Thanksgiving and arrived in Boston that evening. We spent the next three days with Trish's family and our good friends, Chris, Julie, Lili and Wes. We did a 5K Turkey Trot on Thursday morning, followed by football watching and eating succulent turkey while basking in everyone's joy for us. We smiled, giggled, laughed, guffawed, smiled some more and had an all-around great time the rest of the weekend.

We returned home on Sunday evening, departing Boston's Logan airport only minutes after the Broncos kicked a field goal in overtime to beat the Chargers. Our flight was delayed just long enough (3 hours) that we got to watch almost the whole game. It was the perfect ending to a phenomenal trip.

To see more pictures from this adventure, see Trish's fantastic photos and mine on Flickr.

Posted in General at Dec 04 2011, 04:02:34 PM MST 12 Comments

Deploying Java and Play Framework Apps to the Cloud with James Ward

Yesterday, I attended James Ward's presentation on Deploying Java & Play Framework Apps to the Cloud at Devoxx. I arrived a bit late, but still managed to get there in time to see a lot of demos and learn more about Heroku. Below are my notes from James's talk.

When I arrived, James was doing a demo using Spring Roo. He was using Roo's Petclinic sample app and showed us how you could use Git to create a local repository of the new project and install Heroku's command line tool. From there, he ran the following command to create a new application on Heroku.

heroku create -s cedar

The Cedar Stack is what supports Java, Scala and Play Framework. It's the 3rd generation stack for Heroku. The command above created two endpoints, one for HTTP and one for Git. It picks from a list of randomly generated names, which all seem to have some humor in them. James ended up with "electric-sword-8877" for this demo.

From there, he ran git push heroku master to deploy the project to Heroku. Unfortunately, this resulted in a login error and there was an akward moment where we all thought the Demo Gods were angry. However, James was able to resolve this by using Heroku's sharing feature with the following command.

heroku sharing:add [email protected]

For Java projects, Heroku looks for a pom.xml file in the root directory and runs a Maven build on project. All the dependencies get downloaded on the cloud rather than put them into a WAR and requiring you to upload a large WAR file. You don't have to upload your source code to Heroku; James did it for the sake of the demo because it was faster.

After the build finishes, it creates a slug file. This file contains everything Heroku needs to run your application.

Next, James showed a demo of the running application and added a new Pet through its UI. Then he scaled it to two servers using the following command:

heroku scale web=2

He proved this was working by running heroku ps, which showed there were two running processes. He showed the app again, but noted that the record he added was missing. This is because when it started up a new dyno, Hibernate created the schema again and deleted all records. To fix, James changed Hibernate to only update the schema instead of create a new one. If you're a Hibernate user, you know this is as simple as changing:

hibernate.hbm2ddl.auto=create

to:

hibernate.hbm2ddl.auto=update

After committing this change, James redeployed using Git.

git push heroku master

The slug file got built again and Heroku deployed the new slug onto both dynos, automatically load balancing the app across two servers. James then ran heroku logs to see the logs of his dynos and prove that a request to his app's HTTP endpoint made requests to both dynos. The logging is powered by Logplex and you can read about how it works in the article Heroku Gets Sweet Logging.

James mentioned that Roo has a Heroku plugin, but after watching his talk and searching a bit on the internet, it seems it's just the jetty-runner setup as described in Getting Started with Spring MVC Hibernate on Heroku/Cedar.

What about autoscaling? There are some 3rd party tools that do this. Heroku's Management infrastructure has APIs that these tools talk too. Heroku hasn't built autoscaling into the platform because they don't know where the bottlenecks are in your application.

Heroku = Polyglot + PaaS + Cloud Components. It supports Ruby, node.js, Java, Clojure, Play and Scala and they're working on native Grails and Gradle support. There's currently 534,374 apps running on Heroku.

Heroku is a cloud application platform and there's 5 different components.

  1. Instant deployment
  2. HTTP Routing / Load Balancing
  3. Elastic Polyglot Runtime
  4. Management & Logging
  5. Component as a Service Ecosystem

For instant deployment, it's a pretty simple process:

  • You add files to a git repo
  • You provision the app on Heroku (heroku create)
  • You upload the files to Heroku (git push heroku master)
  • Heroku runs the build and assembles a "slug" file
  • Heroku starts a "dyno"
  • Heroku copies the "slug" to the "dyno"
  • Heroku starts the web application

Most apps will contain a Procfile that contains information about how to run the web process. For Spring Roo, it has:

web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

So how does Heroku decide what application server to use? It doesn't, you do. You need to get your application server into the slug file. The easiest way to do this is to specify your application server as a dependency in your pom.xml. In the Roo example, James uses the maven-dependency-plugin to get the jetty-runner dependency and copy it to the target directory. On Heroku, you bring your application server with you.

Heroku gives you 750 free dyno hours per app, per month. For developers, it's very easy to get started and use. Once you extend past one dyno, it's $.05 per dyno hour, which works out to around $30/month. It's only when you want to scale beyond one dyno where you get charged by Heroku, no matter how much data you transfer. Scalatest is running on Heroku. It has one dyno and is doing fine with that. Bill Venners doesn't have to pay anything for it.

java.herokuapp.com is a site James created that allows you to clone example apps and get started quickly with Heroku's Cedar Stack.

For HTTP Routing, Heroku uses an Erlang-based routing system to route all the HTTP requests across your dynos. Heroku doesn't support sticky sessions. Distributed session management does not work well, because it does not scale well. Heroku recommends you use a stateless web architecture or move your state into something like memcached. Jetty has (in the latest version) the ability to automatically serialize your session into a Mongo system. This works fine on Heroku. The problem with this is if you have 2 dynos running, each request can hit a different dyno and get different session state. Hence the recommendation for an external storage mechanism that can synchronize between dynos.

You can also run non-web applications on Heroku. You can have one web process, but as many non-web processes as you want.

Heroku has native support for the Play framework. To detect Play applications, it look for a conf/application.conf file. You don't need to have a Procfile in your root directory because Heroku knows how to start a Play application.

At this point, James created a new Play application, created a new Heroku app (he got "young-night-7104" this time) and pushed it to Heroku. He created a simple model object, a controller to allow adding new data and then wrote some jQuery to show new records via Ajax and JSON. He also showed how to configure the application to talk to Heroku's PostgreSQL database using the DATABASE_URL environment variable. He explained how you can use the heroku config command to see your environment variables.

The reason they use environment variables is so Heroku can update DATABASE_URL (and other variables) without having to call up all their customers and have them change them in their source code.

Play on Heroku supports Scala if you create your app with Scala. Play 2.0 uses Scala, Akka and SBT. Heroku added support for SBT a couple month ago, so everything will work just fine.

Heroku also supports Scala, detecting it by looking for the build.sbt file in the root directory. Heroku supports SBT 0.11.0 and it builds the 'stage' task. It currently does not support Lift because Lift uses an older version of SBT and because it's a very stateful framework that would require sticky sessions. Use Play, BlueEyes or Scalatra if you want Scala on Heroku.

Heroku has addons for adding functionality to your application, including Custom DNS, HTTPS, Amazon RDS, NoSQL and many more. They're also working on making their add-on and management APIs available via Java, so you'll (hopefully) be able to use them from your IDE in the future.

From there, James showed us how Heroku keeps slug files around so you can do rollbacks with heroku rollback. He also showed how you can use:

heroku run "your bash command"
to run any Bash command on the cloud.

Summary
I attended James's talk because he's a good friend, but also because I've been using Heroku to host my latest adventures with Play, Scala, CoffeeScript and Jade. I'm glad I attended because I learned some good tips and tricks and more about how Heroku works.

Heroku seems like a great development tool to me. In my experience, it's been really nice to have instant deployments using Git. In fact, I've created a 'push' alias so I can push to my project's repo and heroku at the same time.

alias push='git push origin master && git push heroku master'

I'd like to see more organizations embrace something like Heroku for developers. It'd be great if everyone had their own sandbox that business owners and product managers could see. I can't help but think this would be awesome for demos, prototyping, etc.

There were some other talks I wanted to attend at the same time, particularly Martin Odersky's What's in store for Scala? and WWW: World Wide Wait? A Performance Comparison of Java Web Frameworks. The WWW talk has posted their presentation but I'm sure it'd be more fun to watch.

It's pretty awesome that all the talks from Devoxx 2011 will be up on Parleys.com soon.

Update: James has posted his slides from this talk.

Posted in Java at Nov 18 2011, 08:14:45 AM MST 2 Comments

PhoneGap for Hybrid App Development

This afternoon, I attended Brian LeRoux's talk on PhoneGap for Hybrid App Development at Devoxx. You might remember that I tried PhoneGap last week and really enjoyed my experience. Below are my notes from Brian's talk.

PhoneGap is a project for creating native applications using HTML, CSS and JavaScript. PhoneGap started out as a hack. In 2007, Apple shipped the iPhone and Steve Jobs told everyone they should develop webapps. PhoneGap started in 2008 as a lofty summertime hack and gained traction as a concept at Nitobi with Android and Blackberry implementations in the fall. In 2009, people started to pay attention when PhoneGap got rejected by Apple. They added Symbian and webOS support and Sony Ericsson started contributing to the project. They got rejected because all PhoneGap-developed apps were named "PhoneGap". This turned out to be good press for the project and Apple let them in shortly after.

In 2010, IBM began tag-teaming with Nitobi and added 5 developers to the project after meeting them at OSCON. In 2011, RIM started contributing as well as Microsoft. Then Adobe bought the company, so they're obviously contributing.

PhoneGaps Goals: the web is a first class platform, so let people create installable web apps. Their second goal is to cease to exist and get browsers to adopt their model.

PhoneGap is NOT a runtime or a compiler/transpiler. It's not an IDE or predefined framework or proprietary lockin. It's Apache, MIT and BSD licensed to guarantee it's as free as free software gets. You can do whatever you want to do with it. PhoneGap has recently been contributed to the Apache Software Foundation.

As far as Adobe vs. PhoneGap is concerned, the Nitobi team remains contributors to PhoneGap. Adobe is a software tools company and has Apache and WebKit contributors. PhoneGap/Build integration will be added to Creative Cloud.

The biggest issues with contributing PhoneGap to Apache is renaming the project and source control. I'm not sure why it needs to be renamed, but it's likely that Apache Callback is out. There seems to be some consensus on Apache Cordova. Apache likes SVN and the PhoneGap community currently uses Git. They're trying to find a medium road there, but would prefer to stay on Git.

The PhoneGap technique is colloquially called "the bridge". It's a 3 step process: they instantiate a WebView, then they call JavaScript from native code, then they call native code from JavaScript. Apparently, all device APIs are available via JavaScript in a WebView.

The primary platforms supported are iOS >= 3, Android >= 1.5 and BlackBerry >= 5.x. They also support webOS, Symbian, Samsung Bada and Windows Phone. No mobile dev platform supports as many deploy targets as PhoneGap. Primary contributors are Adobe, IBM, RIM and Microsoft.

Documentation for PhoneGap is available at http://docs.phonegap.com. Device APIs for PhoneGap 1.0 included sensors, data and outputs, which all devices have. Examples of sensors are geolocation and camera. Data examples are the filesystem, contacts and media. Outputs are screens, speakers and the speaker jack. All PhoneGap APIs are plugins, but any native API is permitted.

What about security? Brian recommends looking at the HTML5 Security Cheatsheet. PhoneGap has added a lot of security measures since they've found the native API pretty much opens up everything.

PhoneGap doesn't bundle a UI framework, but they support any JavaScript framework that works in the browser. PhoneGap is just a fancy browser, so your code run in less fancy web browsers too. This means you can develop and test your app in your desktop browser and only use PhoneGap to package and distribute your app.

Competition? PhoneGap has no competition.

PhoneGap/Build is for compiling your apps in the cloud and free for open source projects. The biggest reason they did this is because they couldn't redistribute all the SDKs and it was a pain for developers to download and install SDKs in training classes.

For mobile app development, you should have a singular goal. Do one thing really well if you want to be successful. Great UX happens iteratively. You know that the web works and has been widely successfully cross-platform. It's likely you've already invested in the web. Start by building a mobile web client and use PhoneGap as a progressive enhancement technique.

Shipping and unit testing should be a daily activity. Automate everything so you can have one-click builds (test/dev/release). For web client design, constraints are your ally in the battle against complexity and "clients who are not chill". Phones suck and consume a lot: cpu, ram, bandwidth, battery, network... everything! Start with a benchmark of app performance and monitor that benchmark. If you have tons and tons of features, consider splitting into multiple apps.

The mobile web is not WebKit! Opera is huge, Firefox is making strides and IE still happens. For layouts: use flex-box rules (anyone got a link to these?), css media queries and meta tags for viewport. You should try to develop your app without frameworks because they come with a ton of code and can effect the size of your app.

Looks can kill: aesthetics that can hurt performance: border-radius, box-shadow and gradients can slow down your apps. Chances are, you really don't need these features. Design your app for your brand, not for the device manufacturer. An app that looks like an iPhone app on Android doesn't give a positive impression.

For JavaScript libraries, start with your problem, not a generic solution like Sencha or jQuery Mobile. Zepto and its older brother XUI are all you need to start. Jo is a fantastic option. Backbone and Spine are worth watching.

For testing, QUnit and Jasmine are pretty popular. For deployment, concat, minify and obfuscate your JavaScript and CSS. Or you can inline everything into the markup to minimize HTTP chatter. Gmail inlines and comments all their JavaScript and then evals it.

From there, Brian recommended leveraging HTML5's AppCache and and using RESTful JSON endpoints for legacy systems. Next, he tried to show us a demo of a photo sharing application. Unfortunately, the Demo Gods were grumpy and Brian couldn't get his computer to recognize his Android phone. He did show us the client code and it's pretty impressive you can use 1 line of code to take a picture on a phone.

The last thing we looked at was debug.phonegap.com. This is an app that's powered by weinre. It lets you enter a line of JavaScript in your client and then remotely debug it in a tool that looks like Chrome's Web Inspector. Very cool stuff if you ask me.

Summary
I really enjoyed learning more about PhoneGap, particularly because Brain emphasized all my web development skills can be used. I don't have to learn Objective-C or Android to develop native apps and I don't even have to install an SDK if I use PhoneGap/Build. Of course, my mobile developer friends might disagree with this approach. In the meantime, I look forward to using PhoneGap to turn my mobile web clients into native apps and finding out if it's really as good as they say it is.

Posted in The Web at Nov 16 2011, 10:22:16 AM MST 2 Comments

Increasing My Developer Happiness

I've bought into the idea that a happy developer requires a clean, attractive, comfortable workplace that encourages healthy, sustainable productivity. Rich Armstrong of Fog Creek Software explains how they spend $6,174 per developer to make them happy. Shortly after reading this article, I tweeted:

My ideal setup is ~$10K more (MacBook Pro, Mac Pro, two 30s).

While this is my ideal setup, it's not something I actually need. If you've ever worked with two 30" monitors, you might agree. That much screen real estate can be too much, as you have to pan your head side-to-side to take it all in. I've found that a single 30" or 27" is good enough for me. As far as a Mac Pro goes, they can have awesome horsepower when full-loaded, but unless you're doing some serious processing, you probably won't utilize it all.

The last time I bought a new computer was March 2009, when I bought a 15" MacBook Pro with an SSD. I upgraded it to 8 GB RAM a year later and it's hummed along just fine since then. I also had the pleasure of working on a fully-loaded Mac Pro at Time Warner Cable for all of 2010 and a company-provided MacBook Pro at Overstock for most of this year. With my recent move to a new client, it's time to increase my developer happiness. Since I am my own boss, it's easy to get hardware upgrades approved. ;)

My current hardware inventory is as follows:

  • A 15" MacBook Pro
  • A 30" monitor at home
  • A 27" monitor at my office in Downtown Littleton

Since I ride my bike to work everyday, I've been hauling my laptop back and forth on my 8-mile commute. This is getting old quickly. I'd rather have a permanent machine in my office and a laptop for when I travel to clients, the mountain office or to conferences. So here's what I hope to buy in the next week:

  • A new 15" MacBook Pro, fastest CPU available
  • A fully-loaded 27" iMac for my office

I'll be moving my current 27" monitor to the mountain office. I plan on getting rid of my current MacBook Pro through the Apple Recycling Program. I'm also planning on trying out Apple's 24-month leasing program. I like to get new hardware every two years and it's a better tax deduction, so it seems to make sense.

My only question at this point is should I get Apple's SSD and RAM instead of getting it aftermarket (e.g. via Crucial)? My original plan was to install an aftermarket SSD and 8 GB RAM in the MacBook Pro. For the iMac, I've heard installing an aftermarket SSD isn't an option, but RAM is. I was thinking about getting the SSD + 1 TB drive combo and upgrading the RAM to 8 GB myself. There's a good chance aftermarket is better quality, but I'd also have to pay more vs. having it wrapped up in the total lease price.

Of course, new hardware is only part of developer happiness. A clean, attractive, comfortable workplace is an essential component as well. My home and mountain offices are nice, but my Littleton office needs work. I currently share it with two other developers, Angela and Jim. Over the next couple months, we plan on making a lot of improvements to our daily digs. I'll make sure and take some before and after pictures and blog about how we improve things.

Update: Thanks to everyone for their advice. As I suspected, upgrading RAM and disk aftermarket is the way to go. When I wrote this, I was under the impression that you couldn't upgrade the iMac's disk. Since then, I've discovered OWC's Turnkey Upgrade Program. Using this, I can send them my iMac and get a wicked fast 480 GB SSD, a 2 TB drive, 16 GB of RAM and have it shipped overnight for around $1400. Add in 8 GB RAM and a 480 GB Mercury Extreme 6G SSD for my new MacBook Pro and I'm looking at $2600 (aftermarket) + $5500 (Apple) = $8100. Now I just need to find some external hard drive enclosures for my old drives. Bonus points if I can find one with Thunderbolt support.

I can feel my developer happiness increasing already...

Posted in Mac OS X at Oct 07 2011, 03:35:35 PM MDT 11 Comments

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