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.

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

Upgrading AppFuse to Spring Security 3.1 and Spring 3.1

Before the holiday break, I spent some time upgrading AppFuse to use the latest releases of Spring and Spring Security. I started with Spring Security in early December and quickly discovered its 3.1 XSD required some changes. After changing to the 3.1 XSD in my security.xml, I had to change its <http> element to use security="none" instead of filters="none". With Spring Security 3.0.5, I had:

<http auto-config="true" lowercase-comparisons="false">
    <intercept-url pattern="/images/**" filters="none"/>
    <intercept-url pattern="/styles/**" filters="none"/>
    <intercept-url pattern="/scripts/**" filters="none"/>
After upgrading to 3.1, I had to change this to:
<http pattern="/images/**" security="none"/>
<http pattern="/styles/**" security="none"/>
<http pattern="/scripts/**" security="none"/>

<http auto-config="true">

The next thing I had to change was UserSecurityAdvice.java. Instead of using Collection<GrantedAuthority> for Authentication's getAuthority() method, I had to change it to use Collection<? extends GrantedAuthority>.

Authentication auth = ctx.getAuthentication();
Collection<? extends GrantedAuthority> roles = auth.getAuthorities();

Lastly, I discovered that SPRING_SECURITY_CONTEXT_KEY moved to HttpSessionSecurityContextRepository. Click here to see the changelog for this upgrade in AppFuse's FishEye.

You can read more about what's new in Spring Security 3.1 on InfoQ. I'm especially pumped to see http-only cookie support for Servlet 3.0. I discovered Spring Security didn't support this when Pen-Testing with Zed Attack Proxy.

Upgrading to Spring Framework 3.1
Compared to the Spring Security upgrade, upgrading to Spring 3.1 was a breeze. The first thing I discovered after changing my pom.xml's version was that Spring Security required some additional exclusions in order to get the latest Spring versions. Of course, this was communicated to me through the following cryptic error.

-------------------------------------------------------------------------------
Test set: org.appfuse.dao.LookupDaoTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.004 sec <<< FAILURE!
testGetRoles(org.appfuse.dao.LookupDaoTest)  Time elapsed: 0.001 sec  <<< ERROR!
java.lang.NoSuchMethodError: org.springframework.context.support.GenericApplicationContext.getEnvironment()Lorg/springframework/core/env/ConfigurableEnvironment;
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:97)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
	at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)

Without these additional exclusions, Spring Security pulled in Spring 3.0.6. I had to exclude spring-expression, spring-context and spring-web from spring-security-taglibs to get the 3.1.0.RELEASE version of Spring.

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

I also had to exclude spring-context from spring-security-config and spring-context and spring-expression from spring-security-core. Isn't Maven wonderful?

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring.security.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
</dependency>

After making these changes, I got a bit further, but ended up being blocked by a bug in Tapestry 5's Spring support. Basically, after upgrading to Spring 3.1, I started seeing the following error:

java.lang.RuntimeException: Service id 'environment' has already been defined by 
org.apache.tapestry5.services.TapestryModule.buildEnvironment(PerthreadManager) 

Luckily, I was able to easily fix this with advice I found on Tapestry's mailing list. Unfortunately, even though I submitted a fix on December 15th, it didn't make it into Tapestry's 5.3.1 release on December 21st. As soon as Tapestry 5.3.2 is released, I hope to get the AppFuse's build passing again (it's currently failing).

I hope this article helps you upgrade your AppFuse-started applications to the latest versions of Spring and Spring Security. Over the next few weeks, I'll be exploring many of Spring 3.1's new features and implementing them as I see fit. Right now, I'm thinking environments/profiles, Servlet 3 / Java 7 support and Hibernate 4 support. These seem to be the best new features to learn about for my talk in a few weeks.

Posted in Java at Jan 05 2012, 08:58:21 AM MST 7 Comments

What have I been working on at Taleo?

2011 has been a year of great clients for me. I started working with O.co and very much enjoyed my time there, especially on powder days in Utah. The people were great, the contract was great (no end date), but the work was not my forte. I was on a project to modularize the main shopping site's codebase, which involved mostly refactoring. By refactoring, I mean creating new Maven projects, modifying lots of pom.xml files and literally moving files from one directory to another. IntelliJ made this easy, the hard part was refactoring tests, moving from EasyMock to Mockito and splitting classes into interfaces and implementations where appropriate. As a developer who likes developing UIs and visually seeing my accomplishments, the project wasn't that exciting. However, I knew that it was strategically important to O.co, so I didn't complain much.

In mid-May, I received a LinkedIn message from the Director of Software Engineering at Taleo.

This is OB, I am the Director of Software Engineering at Taleo. We are the 2nd largest Software as a Service company. I am building a new specialist UI team that will take the product to the next level. I am looking for someone to lead this initiative. If you are interested to have a chat about it, please let me know.

At that time, I'd never heard of Taleo and quickly recommended they not hire me.

This probably isn't the best position for me. While I am a good leader, I'm not willing to relocate from Denver. I've found that leaders usually do best when face-to-face with their developers.

This conversation continued back-and-forth where I explained how I wasn't willing to go full-time and I didn't want to leave Overstock. In the end, OB was persistent and explained how the position would entail lots of UI work and wouldn't require me to travel much. Our negotiations trailed off in June and resumed in July after I returned from vacation in Montana. Shortly after, we met each other's expectations, agreed on a start date and I started working at Taleo in early September.

When I started, there were three features they wanted to add to to Taleo Business Edition: Profile Pictures, Talent Cards and Org Charts. They knew the schedule was tight (8 weeks), but I was confident I could make it happen. At first, I groaned at the fact that they were using Ant to build the project. Then I smiled when I learned they'd standardized on IntelliJ and set things up so you could do everything from the IDE. After using Maven for many years, this setup has actually become refreshing and I rarely have to restart or long for something like JRebel. Of course, a new kick-ass laptop and awesome IDE make it so I rarely wait for anything to happen.

To give you a taste of how I implemented each of these new features in 8 weeks, I've broken them into sections below.

Profile Pictures
Adding profile pictures was a pretty simple concept, one you see on my social networking sites today. I needed to give users the ability to upload a JPEG or PNG and crop it so it looked good. The uploading was a pretty straightforward process and I used a lot of internal APIs to grab the file from the request and save it to disk. The more difficult part was scaling the image to certain dimensions on upload (to save space) and allowing users to crop it after.

Most of Taleo Business Edition (TBE) is written in good ol' servlets and JSPs, with lots of scriptlets in their JSPs. When I saw the amount of HTML produced from Java, I laughed out loud and cringed. Soon after, I breathed a sigh of relief when I learned that any new features could be written using FreeMarker templates, which IntelliJ has excellent support for.

For image resizing on upload, I used Chris Campbell's Image.getScaledInstance() tutorial. For creating thumbnails, I used a combination of scaling, getSubimage() and the Java Image I/O API. I made sure to write to BufferedOutputStream for scalability. For cropping images client-side, I used jQuery UI's Dialog and Jcrop, the jQuery image cropping plugin. Below is a screenshot of what the cropping UI looks like:

Taleo's TBE: Profile Picture

Talent Cards
Talent Cards were a whole different beast. Not only did they need to display profile pictures, they also needed to contain contact information, work history and a number of other data points. Not just for employees, but for candidates as well. They also needed to be rendered with tabs at the bottom that allowed you to navigate between different data sections.

Taleo's TBE: Talent Card I'll admit, most of the hard work for this feature was done by the server-side developers (Harish and Vlad) on my team. Vlad built the tabbed interface and Harish built the administrative section that allows you to add/remove/sort fields, as well as show and hide certain tabs. I performed most of my magic with jQuery, its clueTip plugin and good ol' CSS. I was particularly thankful for CSS3 and its border-radius, box-shadow and Justin Maxwell's tutorial on CSS String Truncation with Ellipsis. I used DWR to fetch all the data from the server using Ajax.

Talent Cards are a slick feature in TBE 11.5 and I think they're a great way to see a lot of information about someone very quickly. If you enable them for your company, you'll be able to mouse over any employee or candidate's names and see their information.

Org Chart
The last feature I completed in this 8-week sprint was creating an organization chart. For this, I was given a rough prototype based on Caprica Software's JQuery/CSS Organisation Chart. When I received it, it had all kinds of cool CSS 3 transformations (like this one), but they only worked in Safari and Chrome. I ended up removing the transformations and adding the ability to navigate up and down the org tree with Ajax (we currently only show three levels at a time).

The Org Chart feature also allows you to see how many direct/indirect reports an employee has, as well as access their Talent Card by hovering over their name. It's one of my favorite features because it's so visual and because it builds upon all the other features we've built.

Taleo's TBE: Org Chart

Summary
As you might've guessed by now, I've been having a lot of fun doing UI development over the last few months. While I seem to have a knack for backend Java development, I enjoy developing UIs a lot more. The smile you see on people's faces during demos is priceless. I can't help but think this kind of thing contributes greatly to my developer happiness. All these features will be in next week's release of TBE and I couldn't be happier.

If you'd like to work on my team at Taleo (or even take over my current role as UI Architect), please drop me a line. If you live near their headquarters (Dublin, CA), it'd also be great to see you at the next Silicon Valley Spring User Group meetup. I'll be speaking about What's New in Spring 3.1 on February 1st.

Posted in Java at Dec 09 2011, 12:57:36 PM MST 1 Comment

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

My HTML5 with Play Scala, CoffeeScript and Jade Presentation from Devoxx 2011

This week, I had the pleasure of traveling to one of my favorite places in the world: Antwerp, Belgium. Like last year, I traveled with the lovely Trish McGinity and spoke at Devoxx 2011. This year, my talk was on developing a web/mobile app with HTML5, Play, Scala, CoffeeScript and Jade. I was inspired to learn Scala at the beginning of this year and added CoffeeScript and Jade to my learning list after talking to James Strachan at TSSJS 2011. You can read more about how my journey began in my first post about learning these technologies.

I started developing with these technologies in August and wrote about my learnings throughout the process. Last week, while writing my presentation, I decided it'd be fun to make my presentation into more of a story-telling-session than a learn-about-new-technologies session. To do this, I focused on talking a bit about the technologies, but more about my experience learning them. I also came up with a challenging idea: create a video that showed the development process, how hard it was to test the app and (hopefully) my success in getting it to work.

It was all a very close call, but I'm happy to say I pulled it off! I got the app to work on an iPhone (thanks to PhoneGap) last Saturday, finished the first draft of my presentation on Sunday night (after pulling an all-nighter) and finished editing the demo video on Wednesday night. My talk was on Thursday afternoon and I had a blast talking about my experience to such a large, enthusiastic audience. You can see the presentation below, on Slideshare or download the PDF.

You can find the "demo" for this talk on YouTube or watch it below.

One of the reasons I really enjoyed this talk is it only represents one milestone in my learning process. I plan on continuing to develop this application and learning more about HTML5, Scala, Play and CoffeeScript and Scalate/Jade. Now that Play 2.0 Beta has been released, I plan on upgrading to it and leveraging its native CoffeeScript and LESS support. I hope to continue using Scalate and its Jade format. And it's very likely PhoneGap will continue to be the bridge that allows everything to run in the background.

I've been talking with the Jfokus folks about doing this talk in Sweden in Feburary and Devoxx France about presenting there in April.

Learning all these technologies has been a challenging, but fun experience so far. As the last slide in my presentation says, I encourage you to do something similar. Pick something new to learn, have fun doing it, but more importantly - get out there and Play!

Update Dec. 20th: A video of this presentation is now available on Parleys.com.

Posted in Java at Nov 18 2011, 11:18:38 AM MST 7 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

Play 2.0, A web framework for a new era

This week, I'm in Antwerp, Belgium for the annual Devoxx conference. After traveling 21 hours door-to-door yesterday, I woke up and came to the conference to attend some talks on Play and PhoneGap. I just got out of the session on Play 2.0, which was presented by Sadek Drobi and Guillaume Bort. Below are my notes from this presentation.

The Play 2.0 beta is out! You can read more about this release on the mailing list. This beta includes native support for both Scala and Java, meaning you can use both in the same project. The release also bundles Akka and SBT by default.

In other news, Play 2.0 is now part of the Typesafe Stack. Typesafe is the Scala company, started by the founder of Scala (Martin Odersky) and the founder of Akka (Jonas Bonér). Guillaume is also joining the Typesafe Advisory Board.

Sadek and Guillaume both work at zenexity, where Play is the secret weapon for the web applications they've built for the last decade. Play was born in the real world. They kept listening to the market to see what they should add to the project. At some point, they realized they couldn't keep adding to the old model and they needed to create something new.

The web has evolved from static pages to dynamic pages (ASP, PHP). From there, we moved to structured web applications with frameworks and MVC. Then the web moved to Ajax and long-polling to more real-time, live features. And this changes everything.

Now we need to adapt our tools. We need to handle tremendous flows of data. Need to improve expressiveness for concurrent code. We need to pick the appropriate datastore for the problem (not only SQL). We need to integrate with rapidly-evolving client side technologies like JavaScript, CoffeeScript, and Dart. We need to use elastic deployment that allows scaling up and scaling down.

zenexity wanted to integrated all of these modern web needs into Play 2.0. But they also wanted to keep Play approachable. They wanted to maintain fast turnaround so you can change your code and hit reload to see the changes. They wanted to keep it as a full stack framework with support for JSON, XML, Web Services, Jobs, etc. And they wanted to continue to use and conventions over configuration.

At this point, Guillaume did a Play 2.0 Beta demo, show us how it uses SBT and has a console so everything so it runs really fast. You can have both Scala and Java files in the same project. Play 2.0 templates are based on Scala, but you don't need to know Scala to use them. You might have to learn how to write a for loop in Scala, but it's just a subset of Scala for templates and views. SBT is used for the build system, but you don't have to learn or know SBT. All the old play commands still work, they're just powered by a different system.

After the demo, Sadek took over and started discussing the key features of Play 2.0.

To handle tremendous amounts of data, you need to do chunking of data and be able to process a stream of data, not just wait until it's finished. Java's InputStream is outdated and too low level. Its read() method reads the next byte of data from the input and this method can block until input data is available.

To solve this, Play includes a reactive programming feature, which they borrowed from Haskell. It uses Iteratee/Enumerator IO and leverages inversion of control (not like dependency injection, but more like not micro-managing). The feature allows you to have control when you need it so you don't have to wait for the input stream to complete. The Enumerator is the component that sends data and the Iteratee is the component that receives data. The Iteratee does incremental processing and can tell the Enumerator when it's done. The Iteratee can also send back a continuation, where it tells the Enumerator it wants more data and how to give it. With this paradigm, you can do a lot of cool stuff without consuming resources and blocking data flow.

Akka is an actor system that is a great model for doing concurrent code. An Actor could be both an Enumerator and an Iteratee. This vastly improves the expressiveness for concurrent code. For example, here's how you'd use Akka in Play:

def search(keyword: String) = Action {
  AsyncResult {
    // do something with result
  }
}

Play does not try to abstract data access because datastores are different now. You don't want to think of everything as objects if you're using something like MongoDB or navigating a Social Graph. Play 2.0 will provide some default modules for the different datastores, but they also expect a lot of contributed modules. Anorm will be the default SQL implementation for Play Scala and Ebean will be the default ORM implementation for Play Java. The reason they've moved away from Hibernate is because they needed something that was more stateless.

On the client side, there's so many technologies (LESS, CoffeeScript, DART, Backbone.js, jQuery, SASS), they didn't want to bundle any because they move too fast. Instead, there's plugins you can add that help you leverage these technologies. There's a lot of richness you can take advantage of on the client side and you need to have the tools for that.

Lastly, there's a new type of deployment: container-less deployment to the cloud. Akka allows you to distribute your jobs across many servers and Heroku is an implementation of elastic deployment that has built-in support for Play.

They've explained what they tried to design and the results of this new, clean architecture have been suprising. Side effects include: type-safety everywhere for rock-solid applications. There's an awesome performance boost from Scala. There's easier integration with existing projects via SBT. And it only takes 10 lines of code to develop an HTTP Server that responds to web requests.

The memory consumption is amazing: only 2MB of heap is used when a Play 2.0 app is started. Tests on Guillaume's laptop have shown that it can handle up to 40,000 requests per second, without any optimization of the JVM. Not only that, but after the requests subside, garbage collection cleans up everything and reduces the memory consumption back to 2MB.

At this point, Guillaume did another demo, showing how everything is type-safe in 2.0, including the routes file. If you mistype (or comment one out) any routes, the compiler will find it and notify you. Play 2.0 also contains a compiled assets feature. This allows you to use Google's Closure Compiler, CoffeeScript and LESS. If you put your LESS files in app/assets/stylesheets, compilation errors will show up in your browser. If you put JavaScript files in app/assets/javascripts, the Closure compiler will be used and compilation errors will show up in your browser.

Play 2.0 ships with 3 different sample applications, all implemented in both Java and Scala. HelloWorld is more than just text in a browser, it includes a form that shows how validation works. Another app is computer-database. When Guillaume started it, we saw how evolutions were used to create the database schema from the browser. The Play Team has done their best to make the development process a browser-based experience rather than having to look in your console. The computer-database is a nice example of how to do CRUD and leverages Twitter's Bootstrap for its look and feel.

The last sample application is zentasks. It uses Ajax and implements security so you can see how to create a login form. It uses LESS for CSS and CoffeeScript and contains features like in-place editing. If you'd like to see any of these applications in action, you can stop by the Typesafe booth this week at Devoxx.

Unfortunately, there will be no migrating path for Play 1.x applications. The API seems very similar, but there are subtle changes that make this difficult. The biggest thing is how templating has changed from Groovy to Scala. To migrate from 1.2.x would be mostly a copy/paste, modify process. There are folks working on getting Groovy templates working in 2.0. The good news is zenexity has hundreds of 1.x applications in production, so 1.x will likely be maintained for many years.

Summary
This was a great talk on what's new in Play 2.0. I especially like the native support for LESS and CoffeeScript and the emphasis on trying to keep developers using two tools: their editor and the browser. The sample apps look great, but the documentation look sparse. I doubt I'll get a chance to migrate my Play 1.2.3 app to 2.0 this month, but I hope to try migrating sometime before the end of the year.

Posted in Java at Nov 16 2011, 05:58:09 AM MST 11 Comments

PhoneGap to the Rescue!

This is the 7th article in a series about my adventures developing a web application with HTML5, Play Scala, CoffeeScript and Jade. Previous articles can be found at:

  1. Integrating Scalate and Jade with Play 1.2.3
  2. Trying to make CoffeeScript work with Scalate and Play
  3. Integrating HTML5 Boilerplate with Scalate and Play
  4. Developing with HTML5, CoffeeScript and Twitter's Bootstrap
  5. Play Scala's Anorm, Heroku and PostgreSQL Issues
  6. More Scalate Goodness for Play
A few weeks ago, I wrote about Developing a Stopwatch and Trip Meter with HTML5. I mentioned I'd run into a major issue when I discovered HTML5 Geo's watchPosition() feature didn't run in the background. From that article:

I tried out the trip meter that evening on a bike ride and noticed it said I'd traveled 3 miles when I'd really gone 6. I quickly figured out it was only calculating start point to end point and not taking into account all the turns in between. To view what was happening, I integrated my odometer.coffee with my map using Google Maps Polylines. Upon finishing the integration, I discovered two things, 1) HTML5 geolocation was highly inaccurate and 2) geolocation doesn't run in the background.

At the time, I opted to ignore this issue and use my app by setting Auto-Lock to Never. This worked, but if I happened to bump my phone while exercising, the app would get closed. Not to mention it really drained the battery and seemed to crash every-so-often.

Last week, I realized things were getting down to the wire and I was running out of time to finish my app's functionality for my Devoxx Talk. On Wednesday afternoon, I asked my office-mates (2 iOS developers) about developing a native app and installing it on my phone. They told me I had to be a iOS Certified Developer ($99/year) or jailbreak my iPhone to get an app on it. On Thursday, I downloaded PhoneGap and installed Xcode 4. As you can tell from the following image, PhoneGap seemed to be exactly what I was looking for.

PhoneGap

I spent some time going through PhoneGap's Getting Started Guide and was able to get my app rendering in a short amount of time. I was able to copy the webapp's generated HTML into my PhoneGap project's www directory and launch the app in the iOS Simulator. The only change I had to make was to convert my inline CoffeeScript (that used coffee-script.js for in-browser compilation) to JavaScript. It's possible the in-browser compiler works, but when things didn't work and I didn't see any error messages, it was the first thing I changed.

For getting the app onto a phone for testing, I opted for the easiest route and applied for an iOS Developer Account on Thursday afternoon. While waiting for approval on Friday, I briefly tried to jailbreak my phone, but encountered all kinds of version issues and gave up after 30 minutes. 24 hours after I applied for my account, Apple emailed asking for a business document to prove I was legit. I was unable to download any from the Colorado Secretary of State that were e-certified, so expeditiously switched my application from a business account to an individual one. Apple was great in helping me out before the weekend started and I had everything I needed as we drove to our Ski Shack on Friday evening.

On Friday night, I upgraded Trish's iPhone 4 to iOS 5 to make sure I had the latest and greatest platform for my app. Saturday morning, I woke up around 8 and started trying to figure out how to get my app on her phone. It took about an hour of fumbling, grumbling and searching to figure out how to do this. All the while, the troops were getting restless, noting that they were hungry for breakfast and groaning about Daddy taking so long. At 9:30, I finally got my PhoneGap app installed on Trish's phone and we drove to breakfast at Sharkey's.

I started the app when we left and checked it 5 minutes later when we arrived for breakfast. The blood drained from my face when I saw the app had drawn a straight line from our condo to the breakfast joint. We had taken several turns along the way and my new native app ignored them all. I assumed I had failed and my talk's conclusion at Devoxx would be "You can't develop a reliable Fitness Tracker app with HTML5". However, after a delicious Eggs Benedict, I became determined to succeed and returned home for some more hacking.

This is when I discovered Joel Dare's Play an MP3 Audio Stream in PhoneGap tutorial and the "Required background modes" key. This was the knowledge that saved the day and I anxiously added the key and the values to get location updates and allow audio to run in the background.

Required Background Modes

Saturday afternoon, I strapped on my recently purchased GoPro Camera, shot some video for my demo at Devoxx and had a blast skiing with Abbie, Jack and Trish. I celebrated that evening with an executive workout (15 minutes each in hot tub, sauna and steam room) at the Fraser Rec Center and again on Sunday when the Broncos whooped the Kansas City Chiefs just like last year.

Last night, I stayed up late to put the finishing touches on my Devoxx presentation. Now I'm sitting at the Red Carpet Club in Chicago's O'Hare getting ready to depart for Belgium. It's been a fun journey learning about HTML5, Scala, Play, CoffeeScript and Jade. If you're at Devoxx this week, I think I've got a presentation you're really going to like. ;-)

Posted in Java at Nov 14 2011, 04:32:19 PM MST 2 Comments

More Scalate Goodness for Play

Scalate This article is the 6th in a series on about my adventures developing a web application with HTML5, Play Scala, CoffeeScript and Jade. Previous articles can be found at:

  1. Integrating Scalate and Jade with Play 1.2.3
  2. Trying to make CoffeeScript work with Scalate and Play
  3. Integrating HTML5 Boilerplate with Scalate and Play
  4. Developing with HTML5, CoffeeScript and Twitter's Bootstrap
  5. Play Scala's Anorm, Heroku and PostgreSQL Issues

Last week, I wrote about my adventures with Anorm and mentioned I'd made some improvements to Scalate Play interoperability. First of all, I've been using a Scalate trait and ScalateTemplate class to render Jade templates in my application. I described this setup in my first article on Scalate and Play.

Adding SiteMesh Features and Default Variables
When I started making my app look good with CSS, I started longing for a feature I've used in SiteMesh. That is, to have a body id or class that can identify the page and allow per-page CSS rules. To do this with SiteMesh, you'd have something like the following in your page:

  
<body id="signup"/>

And then read it in your decorator:

<body<decorator:getProperty property="body.class" writeEntireProperty="true"/>>

As I started looking into how to do this, I came across Play Scala's ScalaController and how it was populating Play's default variables (request, response, flash, params, etc.). Based on this newfound knowledge, I added a populateRenderArgs() method to set all the default variables and my desired bodyClass variable.

def populateRenderArgs(args: (Symbol, Any)*): Map[String, Any] = {
  val renderArgs = Scope.RenderArgs.current();

  args.foreach {
    o =>
      renderArgs.put(o._1.name, o._2)
  }

  renderArgs.put("session", Scope.Session.current())
  renderArgs.put("request", Http.Request.current())
  renderArgs.put("flash", Scope.Flash.current())
  renderArgs.put("params", Scope.Params.current())
  renderArgs.put("errors", validationErrors)
  renderArgs.put("config", Play.configuration)

  // CSS class to add to body
  renderArgs.put("bodyClass", Http.Request.current().action.replace(".", " ").toLowerCase)
  renderArgs.data.toMap
}

implicit def validationErrors:Map[String,play.data.validation.Error] = {
  import scala.collection.JavaConverters._
  Map.empty[String,play.data.validation.Error] ++ 
    Validation.errors.asScala.map( e => (e.getKey, e) )
}

After adding this method, I was able to access these values in my templates by defining them at the top:

-@ val bodyClass: String 
-@ val params: play.mvc.Scope.Params
-@ val flash: play.mvc.Scope.Flash

And then reading their values in my template:

body(class=bodyClass)
...
- if (flash.get("success") != null) {
  div(class="alert-message success" data-alert="alert")
    a(class="close" href="#") &×
    | #{flash.get("success")}
- }
...
  fieldset
    legend Leave a comment →
    div.clearfix
      label(for="author") Your name:
      input(type="text" name="author" class="xlarge" value={params.get("author")})
    div.clearfix
      label(for="content") Your message:
      textarea(name="content" class="xlarge") #{params.get("content")}
    div.actions
      button(type="submit" class="btn primary") Submit your comment
      button(type="reset" class="btn") Cancel

For a request like Home/index, the body tag is now rendered as:

<body class="home index">
This allows you to group CSS styles by Controller names as well as by method names.

Next, I started developing forms and validation logic. I quickly discovered I needed an action() method like the one defined in ScalaTemplate's TemplateMagic class.

def action(action: => Any) = {
  new play.mvc.results.ScalaAction(action).actionDefinition.url
}

Since TemplateMagic is an inner class, I determined that copying the method into my ScalateTemplate class was the easiest workaround. After doing this, I was able to import the method and use it in my templates.

-import controllers.ScalateTemplate._
...
form(method="post" class="form-stacked" id="commentForm"
     action={action(controllers.Profile.postComment(workout._1.id()))})

After getting the proper URL written into my form's action attribute, I encountered a new problem. The Play Scala Tutorial explains validation flow as follows:

if (Validation.hasErrors) {
  show(postId)
} else {
  Comment.create(Comment(postId, author, content))
  Action(show(postId))
}

However, when I had validation errors, I end up with the following error:

Could not load resource: [Timeline/postComment.jade]

To fix this, I added logic to my Scalate trait that looks for a "template" variable before using Http.Request.current().action.replace(".", "/") for the name. After making this change, I was able to use the following code to display validation errors.

if (Validation.hasErrors) {
  renderArgs.put("template", "Timeline/show")
  show(postId)
} else {
  Comment.create(Comment(postId, author, content))
  Action(show(postId))
}

Next, I wanted to give child pages the ability to set content in parent pages. With SiteMesh, I could use the <content> tag as follows:

<content tag="underground">
  HTML goes here
</content>

This HTML could then be retrieved in the decorator using the <decorator:getProperty> tag:

<decorator:getProperty property="page.underground"/>

With Scalate, I found it equally easy using the captureAttribute() method. For example, here's how I captured a list of an athlete's workouts for display in a sidebar.

- captureAttribute("sidebar")
  - Option(older).filterNot(_.isEmpty).map { workouts =>
    .older-workouts
      h3
        | Older workouts
        span.from from this app
      - workouts.map { workout =>
        - render("workout.jade", Map('workout -> workout, 'mode -> "teaser"))
      - }
  - }
- }

Then in my layout, I was able to retrieve this and display it. Below is a snippet from the layout I'm using (copied from Twitter's Bootstrap example). You can see how the sidebar is included in the .span4 at the end.

-@ val sidebar: String = ""
...
.container
  .content
    .page-header
      h1
        = pageHeader
        small
          = pageTagline
    .row
      .span10
        !~~ body
      .span4
        = unescape(sidebar)
  footer

View vs. Render in Scalate
In the sidebar code above, you might notice the render() call. This is the Scalate version of server-side includes. It works well, but there's also a view() shortcut you can use if you want to have templates for rendering your model objects. I quickly discovered it might be difficult to use this feature in my app because my object was Option[(models.Workout, models.Athlete, Seq[models.Comment])] instead of a simple object. You can read the view vs. render thread on the Scalate Google Group if you're interested in learning more.

Scalate as a Module
The last enhancement I attempted to make was to put Scalate support into a Play module. At first, I tried overriding Play's Template class but ran into compilation issues. Then Guillaume Bort (Play's lead developer) recommended I stick with the trait approach and I was able to get everything working. I looked at the outdated play-scalate module to figure out how to add Scala support to build.xml and copied its 500.scaml page for error reporting.

In order to get line-precise error reporting working, I had to wrap a try/catch around calling Scalate's TemplateEngine.layout() method. Again, most of this code was copied from the outdated play-scalate module.

case class Template(name: String) {
  
  def render(args: (Symbol, Any)*) = {
    val argsMap = populateRenderArgs(args: _*)
    
    val buffer = new StringWriter()
    var context = new DefaultRenderContext(name, scalateEngine, new PrintWriter(buffer))
    
    try {
      val templatePath = new File(Play.applicationPath+"/app/views","/"+name).toString
        .replace(new File(Play.applicationPath+"/app/views").toString,"")
      scalateEngine.layout(templatePath + scalateType, argsMap)
    } catch {
      case ex:TemplateNotFoundException => {
        if(ex.isSourceAvailable) {
          throw ex
        }
        val element = PlayException.getInterestingStrackTraceElement(ex)
        if (element != null) {
           throw new TemplateNotFoundException(name, 
             Play.classes.getApplicationClass(element.getClassName()), element.getLineNumber());
        } else {
           throw ex
        }
      }  
      case ex:InvalidSyntaxException => handleSpecialError(context,ex)
      case ex:CompilerException => handleSpecialError(context,ex)
      case ex:Exception => handleSpecialError(context,ex)
    } finally {
      if (buffer.toString.length > 0)
        throw new ScalateResult(buffer.toString,name)
    }
  }
}
...
private def handleSpecialError(context:DefaultRenderContext,ex:Exception) {
  context.attributes("javax.servlet.error.exception") = ex
  context.attributes("javax.servlet.error.message") = ex.getMessage
  try {
    scalateEngine.layout(scalateEngine.load(errorTemplate), context)
  } catch {
    case ex:Exception =>
      // TODO use logging API from Play here...
      println("Caught: " + ex)
      ex.printStackTrace
  }
}

private def errorTemplate:String = {
  val fullPath = new File(Play.applicationPath,"/app/views/errors/500.scaml").toString 
  fullPath.replace(new File(Play.applicationPath+"/app/views").toString,"")
}

Once I had this in place, error messages from Scalate are much better. Not only do I see the error in my browser, but I can click on the offending line to open it directly in TextMate.

Play Scalate Error Reporting

I've published my play-scalate module on GitHub so others can try it out. To give it a whirl, add the following to your dependencies.yml:

    - upgrades -> play-scalate 0.1

repositories:
    - upgrades:
        type: http
        artifact: "http://static.raibledesigns.com/[module]-[revision].zip"
        contains:
            - upgrades -> *

Then add with play.modules.scalate.Scalate to your controllers and call the render() method.

Summary
After using Scalate and Play for almost 3 months, I'm really enjoying the combination. When I first integrated Scalate with a simple trait, the error messages were always in the console. Now that I've borrowed some smarts from Play's ScalaController and play-scalate's error reporting, I feel like it's practically a built-in solution. I was easily able to integrate my desired SiteMesh features and it even allows reusable template blocks. In the end, it's just Scala and Scalate does a good job of allowing you to leverage that.

Other thoughts:

  • If you're writing a lot of Jade and familiar with HTML, Don Park's html2jade is a great tool that comes with Scalate support.
  • I'm really enjoying writing CSS with LESS, particularly the ability to nest rules and have programming features. The only issue I've seen is IntelliJ's LESS plugin only does code-completion for variables rather than CSS values.
  • The Play Framework Cookbook is a great reference for learning how to write modules. Not only does it explain how to create modules, it has some great real-world examples for doing bytecode enhancement, implementing message queues, using Solr and how to do production monitoring.

If this series of articles has intrigued you and you'll be at Devoxx next week, you should stop by my talk on Thursday afternoon. In addition, there's several other Play talks at Devoxx and a possible meetup on Wednesday. Check out the Devoxx, anyone? thread for more information.

Update: There's one thing I forgot to mention about the Play Scalate Module. When I had Scalate integrated in my app with a trait, I only included the scalate-core and scalate-util JARs in dependencies.yml:

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

However, when I created the play-scalate module, I allowed more dependencies.

- org.fusesource.scalate -> scalate-core 1.5.2-scala_2.8.1:
    exclude:
        - javax.servlet -> *
        - com.sun.jersey -> *
        - org.osgi -> *
- org.fusesource.scalate -> scalate-util 1.5.2-scala_2.8.1
Because Scalate depends on Logback, debug messages started showing up in my console. To fix this, I created conf/logback.xml in my project and filled it with the following XML.

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
          <pattern>%msg%n</pattern>
      </encoder>
  </appender>

  <root level="info">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

This reduces the logging and allows me to increase Scalate's logging if I ever have the need.

Posted in Java at Nov 07 2011, 02:07:40 PM MST Add a Comment