Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

Saturday
Feb162013

Quizzo - it's baaack - but this time for keeps

Hey everybody!

For my ETE talk, and our internal Chariot Day conference beforehand, I've taken on client-side Single-Page-Web-Application (SPWA) Javascript programming. I started by attempting to learn Backbone.js, but this poor old server-side programmer with a smattering of front-end talents grounded hard on the shallow waters of confusion.

I was not alone. At SpringOne/2GX 2012, VMware's Craig Walls hosted a talk comparing SPWA frameworks, and discussed Backbone's lack of a 'day one story' - a starting point example. He was really interested in the Walmart Labs projects Thorax and Lumbar, which are attempting to bring some higher-level structure and organization to the code base. Also, I ran into the emerging but not yet complete Yeoman
Then Chariot's Don Coleman turned me on to Addy Osmani's TodoMVC project - it implements the same task list use case in oh, about 18+ frameworks.

I spent time looking at each of them and AngularJS caught my eye. It has two-way instant data synchronization, is agnostic with respect to your models, contains a good basic validation scheme, and uses tags and attributes salted to the templates to expose a 'ViewModel' to the view.

What is a view model?

A ViewModel is an element of your MVC model that should be exposed to the page. Spring MVC has this concept - we put things in the Model object to show to the users, but rarely do we put true domain objects in there. If you have web-only beans that you send back-and-forth to the UI, chances are you're using the ViewModel pattern (please let me know if that is a wrong assumption).

A sample view

Let's review some code from our current Quizzo-ETE project, a collaboration with David Turanski of VMware for our upcoming Modern Spring Web Applications talk. We're using AngularJS and Spring to show enterprise developers how to leverage their skills in Spring but also quickly get onboard with a very powerful SPWA framework.

First, a simple view fragment, showing how to emit model elements:

<tr>
    <th span="2">Statistics</th>
</tr>
<tr>
    <th>Score</th>
    <td>{{statistics.score}}</td>
</tr>
<tr>
    <th>Max Score</th>
    <td>{{statistics.maxScore}}</td>
</tr>
<tr>
    <th>% Correct</th>
    <td>{{statistics.percentCorrect}}</td>
</tr>

So, you can see the handlebars-style substitutions of ViewModel elements using the {{ and }} characters.

A sample Angular controller

Here is the Angular controller that put the data in there in the first place:

myApp.controller('ByeCtrl', function($scope) {
  $scope.statistics = {
    "score": "130",
    "maxScore": "150",
    "percentCorrect": "86%",
    "topScorers": ['phil', 'joe', 'alex']
  };

The $scope object is our ViewModel. We're adding a Javascript object called

statistics

to it, hardcoding it for now.

Two-way databinding

The cool thing is that if anything on the page changes the objects, the page changes immediately. A click, an event, even a message from the outside world, can trigger a UI update. The same works the other direction with form elements. Consider this fragment:

  <form class="panelform left">
    <p>
        <label for="nickname"><b>Nickname</b></label>
        <input type="text" 
               ng-model="nickname"
               ng-change="verify_nick(nickname)"
               id="nickname"
                /> 
        <span ng-show="badNick" class="error">
                        Nickname already used...</span>

    <button id="join" ng-click="join_game($location)"
      ng-show="!badNick && nickname">Join</button>
    </p>
</form>

Handling events

The input tag has some special attributes in it - ng-model, which automatically binds the typed in value (live, no less, not even requiring a submit) to a $scope element called nickname. We trigger verification by calling a controller method called verify_nick, passing the nickname into the call. Here is what the controller looks like:

myApp.controller('JoinCtrl', function ($scope, $location, PlayerService, QuizManagerService) {

  $scope.verify_nick = function () {
    var result = PlayerService.searchNickName($scope.nickname);
    $scope.badNick = result;
  };

  $scope.join_game = function (nickName, emailAddress) {
    PlayerService.setNickName(nickname);
    QuizManagerService.startQuiz();
    $location.path("/play");
  };


});

You can see interactions with several objects. For Spring fans, we inject objects in a similar way to how Spring MVC does it - add it to the function's parameter list and it gets injected. NICE.

Services

We inject and use several objects:

  • $scope - our ViewModel
  • $location - allows us to change the page fragment we're showing
  • PlayerService, QuizManagerService - these are stateful service objects that live inside of the browser. Think of them as holding your state and calling business methods, and you're on the right track.

You should note that in this function, we're adding two other named functions to the ViewModel - verify_nick and join_game. Also, for those Spring developers you'll see us delegating most work to our named Service and built-in Angular objects. Just like a good MVC, it's just a front-end. The services do all the work.

Summary

That's all for now, and if you check out the commit with version 33607951b734a0f1cfc8a710b41abd8664cc3e8f you can run the app this way:

  • first, install node.js - 0.8 +
  • next, do a 'npm install -g express'
  • cd to ./angular-prototype/app
  • run the server with node server.js
  • browse to http://localhost:4567

It looks TERRIBLE right now. But it is a working app with several panes. I'm using Twitter bootstrap on the front-end so expect some ugliness until I get that smoothed out.

To re-iterate, our code is online - please feel free to watch our progress and comment away here if you like, but expect lots of silly steps as we move along). It's at http://github.com/krimple/quizzo-ete.

Saturday
Feb162013

Philly Emerging Tech 2013 - sold out!!

Perhaps it's a bit expected, but the 2013 Emerging Technologies for the Enterprise conference just sold out yesterday. As before, it sold out at the end of the early bird registration, so everybody saved $75!

We have a FANTASTIC show coming up. Just look at the website, phillyemergingtech.com, and you'll see. We have Doug Lea, Cliff Click, Ken Scwaber, Aaron Patterson, the committers of at least five or six javascript single-page and server frameworks, and the list goes on, and on.

As we did last year, we ARE going to record the screens this year of almost every talk (forgive us if we have a technical glitch or two). We won't be streaming live, but we will be doing our best to get the talks out when we can.

So, if you aren't able to go, within a few months we should have the talks available online. Watch the @Chariotsolution or @krimple twitter accounts for the announcements. And you can browse all of our other content at our content site, emergingtech.chariotsolutions.com, including just about all of the 2012 talks, our Science of Big Data conference materials, and over 100 podcasts from the past five years.

Ken

Friday
Jan042013

Philly Emerging Tech April 2-3 2013 - Register today!

Remember that conference in the spring? Well, it's baaack! Yep, it's 2013, and so we are full-steam ahead, planning for the next Emerging Technologies for the Enterprise Conference, to be held at the Sheraton Olde City in beautiful Philadelphia on April 2-3.

We have quite the show lined up for you, with keynotes from Rich Hickey, the creator of the Clojure language, and Media Six Degrees' Chief Data Scientist, Claudia Perlich. Notable speakers include Ember.js creator (among other things) Yehuda Katz, Jessica McKellar of the Boston Python User Group, contributor to the Python Twisted async network library, the inimitable Aaron Patterson (if you want a laugh, listen to him rib us about our conference name in his Code Chacuterie talk of 2012)...

Also we have Cliff Click (0xdata), author of "Java Performance" Charlie Hunt, Go contributor and creator of Sinatra Blake Mizerany, author of "The Culture Game - Tools for the Agile Manager" Dan Mezick, Jurgen Appelo (author of Management 3.0), the creator of the Scrum process, Ken Schwaber, and more are being added every day.

We even have Angluar.js expert Lukas Ruebbelke (see Angular.js), a Google-sponsored "single page Javascript" client-side application framework that uses JSON/REST and has live two-way data binding. (I didn't even realize we booked him when I published this so ignore my earlier version where I said I am speaking on this topic). And as usual we'll be recording sessions and hopefully podcasting too.

More speakers are being booked each week.

So, don't delay. Last year we sold out with two months to go, and I think as we add additional awesome speakers the competition for a ticket will get intense. Register today at phillyemergingtech.com.

If you want more incentives, the early bird registration is just $385, and ends on February 15th. After that prices go up to $450 (still a steal, but why not save and register now, will ya?)

Wednesday
Dec192012

The future of Web MVC testing

Ok, ok, I'm excited. Right now I just was able to hack my way through a test with Spring 3.2 and the new test web context.

The method I ended up writing looked like this:

@Test
public void tryStartQuiz() throws Exception {
   this.mvc.perform(get("/engine/start/james"))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON))
        .andExpect(jsonPath("$.quiz_id").exists());
}

How did I get here?

I upgraded to Spring 3.2, which has native support for loading Web contexts (well, not in a separate-but-parent/child way where you can mount the web context and business context separately, that's coming, but in one context).

Here is the top of my test class:


import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
   "file:src/main/webapp/WEB-INF/spring/webmvc-config.xml", 
   "classpath:/META-INF/spring/applicationContext.xml"})
public class EngineControllerTest {

    @Autowired
    WebApplicationContext context;

    MockMvc mvc;

    @Before
    public void setUp() {
        mvc = webAppContextSetup(this.context).build();
    }

    ...

Some analysis...

The MockMvc object, which I referred to as this.mvc in my test, allows me to mock up the web container request and record expectations. It is created in the @Before method, after Spring injects a test WebApplicationContext object, which is driven via the @WebAppConfiguration above.

The WebApplicationContext object is a web app engine in a test engine. It boots a Spring MVC platform, mocking the network engine so that you can submit requests with calls like mvc.perform(get(...) ... and chain assertions, using .andExpect statements to build conditions. It's like headless Spring MVC. This allows you to test by submitting URLs but without having to configure Jetty or Tomcat in a complex server bootstrapped integration test.

But where is it looking for my webapp?

As a nice touch, the default path for the web application is src/main/webapp. If you're not mavenized, or have a test version of your webapp you want to use, you can submit the path to it as the value of the annotation, like:

@WebApplicationContext("src/test/lightweightwebapp")

Assertions and matchers

There are several static imports that make life easier, as outlined in this great slide show from the MVC team (Rossen and friends):

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

I had to hack a bit with the commands and don't have the DSL figured out much so far. But it is nice to test through the request dispatcher rather than inject a controller directly. It's more natural and lets you really test the way production will handle your requests/responses.

What about more sophisticated checks?

The expect syntax doesn't really allow dicing and slicing of the response as easily as grabbing it in a variable. You can tell the mock MVC object to return the result, which contains the MockHttpServletResponse. In this example, I'm using FlexJson (from Roo's dependencies) to deserialize the JSON request into a HashMap of string keys and values, and assert that the data exists in the proper format.

@Test
public void tryStartQuiz() throws Exception {
	JSONDeserializer<HashMap<String, String>> deserializer
			= new JSONDeserializer<HashMap<String, String>>();

	MvcResult result = this.mvc.perform(get("/engine/start/james"))
			.andExpect(status().isOk())
			.andExpect(content().contentType(MediaType.APPLICATION_JSON))
			.andExpect(jsonPath("$.quiz_id").exists())
			.andReturn();

	Map<String, String> jsonPayload =
			deserializer.deserialize(
					result.getResponse().getContentAsString());

	assertThat(jsonPayload.containsKey("quiz_id"), is(true));
	assertThat(jsonPayload.get("nickname"), is("james"));

	System.err.println(jsonPayload);


}

Roo and Spring 3.2

One more thing - I came from Roo 1.2.2, and as I upgraded the spring.version property to Spring 3.2 (yes, it works just fine) so I had to add one dependency in order for this to work, test scoped:

<dependency>
	<groupId>com.jayway.jsonpath</groupId>
	<artifactId>json-path</artifactId>
	<version>0.8.1</version>
	<scope>test</scope>
</dependency>

Roo was just upgraded to version 1.2.3 this week (check it out here). I am hoping it uses Spring 3.2 out of the box.

This test will be checked into the next update of Quizzo-Angular-Roo - my current obsession which is using Spring Roo on the backend, and Angular.JS on the front-end, for a single-page JS quiz engine.

Where to go to view the code?

Today I've pushed this code (somewhat modified) along with working Jasmine tests, AND a working Maven test suite that includes automatic Jasmine testing every time I run mvn test. Check it out at quizzo-angular-roo on GitHub. I warn you, it will be primitive and so far not really doing much, but it will shape up over time.

Tuesday
Nov202012

todo-txt - very cool GTD task management from anything

So, just I stumbled on Gina Tripani's todo-txt project when searching for a cross-device todo management system. I am switching from an iPhone to an Android device as I'm prepping to provide some Android training for Chariot in the early part of next year.

todo-txt is a very simple format. Described here and with a client for virtually anything (including the command-line, vim, Android, iOS, even WebOS) you can use it from anything, even a text editor. The clients are all savvy with Dropbox, so putting it on ~/Dropbox/todo is all you need to do.

Here is a groovy script I just wrote up to play with my todo list...

def todoFile = new File('./todo.txt')
def fileReader = new FileReader(todoFile)
def todos = fileReader.readLines()
def projects = [:], contexts = [:]
todos.each { it ->
  println it
  def tokenizer = new StringTokenizer(it)
  while (tokenizer.hasMoreTokens()) {
      def token = tokenizer.nextToken()
      if (token.startsWith("@")) {
          def size = contexts[token] ? contexts[token] : 0
          contexts[token] = size + 1
      }
      if (token.startsWith("+")) {
          def size = projects[token] ? projects[token] : 0
          projects[token] = size + 1
      }
    
  }
}
fileReader.close()

projects.each { key, value -> 
  println "Project ${key} : ${value} tasks"
}

println ""
contexts.each { key, value -> 
  println "context ${key} : ${value} tasks"
}

Fun, eh? Now I can rid myself of the OS X reminders system - although I could really use the ability to store these in my Google calendar as timed events with due dates... Hmm...