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


Chariot Emerging Tech

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


Chariot Conferences


Entries in quizzo-in-roo (14)


Dojo 1.7 is quite different

I've been having a lot of fun dodging and perrying through a full Javascript UI for Quizzo. I know, it sort of subverted the original intent of getting it out there fast, but I'm thinking there is a good Roo add-on lurking in here. Specifically around controlling the actions of the Quiz - somehow I need to let all of the players know that the time is up for their current question, or that new scores appeared, or any number of other things.

I could poll, but I'm thinking that would be expensive. Sure, you can use setInterval(ms, function) and ask every four seconds, like I'm doing now (quite amatuerish, I'm sure but then that's what I am in the JS UI department at the moment):

 function (dom, registry, xhr) {

   pollScores = function pollScores() {
       url: "${quizzo_scores_url}",
       handleAs: "json",
       load: function(data) {
         var yourScore = dom.byId("scores");
         var targetStr = "";
         yourScore.innerHTML = "";
         data.score.forEach(function(scoreValue) {
         //TODO - make this nice with spans and a div for each score instead
         //TODO - put on rhs in layout
         targetStr += + " : " + scoreValue.value + "<br />";
        yourScore.innerHTML = targetStr;

       error: function(err) {
         dom.byId("yourScore").innerHTML = "error.";

... later that same evening ...

window.setInterval(pollScores, 4000);

But that would be rather inefficient. However, for those looking to manipulate some DOM elements, call some Ajax, and update parts of HTML using Dojo 1.7, at least it's some useful information, so I'll post it.

Instead of polling, communicate on channels

Our CTO Aaron Mulder talked about WebSockets at our Chariot Day last weekend. Other developers in our group including Don Coleman and Steve Smith have been using jQuery UI, jQuery Mobile, Sencha Touch, etc., and tools like Handlebars.js to provide data bindings and other features.

But since I'm investing some time in Dojo and related projects, I want to see how far I can dig and what I can offer to the Roo community from this research. So, I found a project that the Dojo foundation has been using, CometD which in the most recent versions supports WebSockets as a transport medium. It's an asychronous communication mechanism for subscribing to and publishing messages without forcing programmatic polling.

My initial goal for server-side push is to broadcast messages on a hub-and-spoke pub/sub channel, broadcasting these events:

  • Updated scores
  • General messages from the quiz master
  • Change of game state (team registration time, question available, voting open, voting closed, results, end of game)

Maybe the third one needs some refinement, especially since it could be tough to make sure the clients actually got the messages. But at least it's a way of making the control of those activities a little more coordinated.

What's in the repo now?

So far, I've migrated the code for the admin/moderator and quizzo URIs to use Dojo 1.7.2, and embedded 1.7.2 as a library in src/main/resources. The tests still fail on some machines, so -Dmaven.test.skip=true is a necessity. Also, if you're playing around you may need to change the persistence.xml to create schema elements at first, then go back and change it back.

The UI is NOT ready.

If you have a spreadsheet of questions and answers, you'll find that handy class in the test directory as well.

I'm going to focus on making the question/answer views, using polling for now (because it's easy) to check on the current project state. I'll post when I have it working (soon).

Next, I'll event-ize the moderator communications.

This will end up generating one or two add-ons, I'm sure. Of course, I'm under the gun for my ETE presentation and need some additional add-ons to show off, so synergy will be my friend.

Watch this space.


Quizzo - javascript speed bump = fallback plan...

In a word, AARGH.

I got stuck in Javascript / Dojo debug hell the few days leading up to our internal conference. Unfortunately, that meant that Quizzo had to happen without my software. However, that's life, and I had a fallback plan.

For those of you keeping score, it's the second time Dojo / Javascript hung me out to dry - the first time was during the writing of Spring Roo in Action over a year ago. I don't know if it is me, but it certainly is very painful to debug problems with Dojo, at least in the embedded 1.x version and in 1.6.1. I want to upgrade this game to 1.7.2 and see if the debugging got any better.


So, I apparently don't know my Dojo. Or maybe even how to read. Because there is a (admittedly very old) helpful tutorial on the Dojo site that explains my very problem. Long story short, you have to add debugAtAllCosts: true to your dojo config parameters. Here is my current setting:


Ahhhh, if only I read that debugging page before last Saturday, I'd be a much happier person. Without this change, stack traces and errors in Dojo look incredibly incoherent. With it, it actually tells you what is wrong in your Javascript console.

The fallback plan

Ok, so we had to take all of the questions that everybody submitted and import them into a database. Did you know Spring makes an excellent command-line tool?

 public static void main(String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext(

    quizService = context.getBean(QuizService.class);
    questionService = context.getBean(QuestionService.class);
    choiceService = context.getBean(ChoiceService.class);



We ended up using it like a swiss army knife to pull the data in using the Apache POI library, and write it out using our services. Here is the parseAndProcess, which I just grabbed from a sample and then manipulated to suit my needs.

Here is a (admittedly quickly dashed off) snippet:

 private static void parseAndProcess(String fileName) {

    Quiz quiz = new Quiz();
    quiz.setTitle("Chariot Day Quizzo!");
    quiz.setDescription("Because a day without night would be, what would it be?");

    List cellDataList = new ArrayList();
    try {
      FileInputStream fileInputStream = new FileInputStream(fileName);
      POIFSFileSystem fsFileSystem = new POIFSFileSystem(fileInputStream);
      HSSFWorkbook workBook = new HSSFWorkbook(fsFileSystem);
      HSSFSheet hssfSheet = workBook.getSheetAt(0);
      Iterator rowIterator = hssfSheet.rowIterator();; // skip top header

      short questionIdx = 0;
      while (rowIterator.hasNext()) {
        HSSFRow hssfRow = (HSSFRow);

        // get all quiz rows
        Iterator iterator = hssfRow.cellIterator();
        HSSFCell questionOrderCell = (HSSFCell);
        short order = (short) questionOrderCell.getNumericCellValue();
        String questionText = ((HSSFCell);

        Question question = new Question();

        HSSFCell correctAnswerCell = (HSSFCell);

        int correctAnswerPosition =
            BigDecimal.valueOf(correctAnswerCell.getNumericCellValue()).intValue() - 1;
        short curIdx = -1;
        while (iterator.hasNext()) {
          String answerText = ((HSSFCell);

          Choice choice = new Choice();
          choice.setPointValue(new BigDecimal("1.0"));
          curIdx ++;
          choice.setCorrect(curIdx == correctAnswerPosition);

    } catch (Exception e) {

I used this entry in my pom.xml:


So what did you do?

I ended up using a Ruby-based slide presentation project called Showoff. It requires installation of a Ruby gem, showoff:

$ gem install showoff

You can use showoff to set up a sample slide show:

showoff create presentationname

This command creates a new slideshow. Poke around and have fun. The project website is on github at

What's next for Quizzo?

Now that I've been given a reprieve, I'm going to dig deeper. I'll be upgrading Dojo to 1.7.2, showing you how to debug widgets, and cleaning up the user interface. We'll have to tackle some sophisticated problems, such as managing state, what happens when we hit the refresh button, and more.

Stay tuned over the next few weeks. We'll also try to extract some of what we're doing and put it into a new Roo add-on.


Quizzo - it's THURSDAY? Must go into the Dojo and meditate

You know how if you don't have anything nice to say, don't say it at all? Mmm hmm... Except it was a conversation with myself that started "why the heck don't you know THAT?"...

Where the heck were you?

Ok, ok, I was busy with my day job. Training at Chariot is really getting busy, which is great because I run that group! If you're looking for public or private training in Spring, Maven, Hibernate, and a number of other technologies, check us out.

Shameless plug-meister, what are you doing with the quizzo??

Ok, it's back to reality. I've been taking an alternate path with the quizzo UI. Since Chariot Day is a chance to stretch a bit, I figure I'd do the admin and perhaps main front-end as a rich Javascript UI, Roo-style. That comment about not saying anything nice? It was about a library I wish Roo would leave behind. It's called Spring Javascript.

Spring Javascript?

If you're thinking "Cool, a Spring Container in Javascript" - a) stop RIGHT there, dude, and b) it's not what you think. c) that's pretty nifty, but I understand there is a movement out there for MVC and strong binding in the Javascript community. I know nothing about it, but some of Chariot's mobile team do. Read here, here, here, here, and oh, here. Did I mention we're a consulting firm?

Spring Javascript is a Javascript library written for the WebFlow project. The idea was that if you wanted to roll out client-side validation, ajax forms, or any widgets from a Javascript toolkit, you'd use this library. It also has this wrapper around doing partial rendering of Ajax Tiles (or JSF fragments, I think). Nifty.

The Spring Javascript library is a thin wrapper around a Javascript toolkit called Dojo.

Bow to your Sensai - what is Dojo?

Roo's view layer heavily uses Dojo. Those neat little client-side validations? Dojo. The panels with the little titlebars? Dojo - that's the dijit.layout.TitlePane.

The reason for choosing Dojo makes sense for me. At the time it was a very comprehensive widget toolkit and in 2008 it was gaining in popularity. Just look at the date of the books published and you'll get the idea. Sitepen is a supporter of the library and IBM and a number of large organizations use it. It has a great open community as well, and is funded by a not-for-profit organization.

But then a lot of developers turned left at jQuery. The focus has been on a more wide-open platform, with the curation of components being primarily the user's job. Think "platform-and-plugins" and you're on to it.

Dojo hasn't changed their approach. In fact, I really like the concept of how they focus themselves on curation, incorporation of experimenta components into an extensions library, and the coherence of the whole library.

So, what about Spring Javascript

The reason I'm not a fan of Spring Javascript is that it is kind of an artifact of where the thinking was in 2007/2008, and hasn't moved on. Spring Javascript hides about 40% of the construction of Dojo widgets (known as Digits (dijit)). But it's a leaky abstraction; you need to know Dojo to program it after all, and Roo only really uses it for validation sugar.

Here is a Spring Javascript snippet to create a title pane, which you can find in WEB-INF/tags/utils/panel.tagx:

    <div id="_title_${sec_id}_id" class="panel">
      <jsp:doBody />

I've highlighted the lines where Dojo isn't hidden. You're mounting a Dojo TitlePane, and to do so, you need to know:

  • The Dojo specifics of the class
  • The various attributes of the widget
  • What widget (dijit) to import

So, not really encapsulating the framework.

How Dojo wants to be used

Dojo is a flexible framework. It has at least three ways to use it. First, you can programmatically create a component like a title pane.

In Javascript:


  var tp;
      tp = new dijit.TitlePane({title:"Quiz Administrator", content: "Show my content here"});

In HTML with a page parser (this is the pre-Dojo 1.7 version):

  <div dojoType="dijit.layout.TitlePane" title="hiya dude">
     <p>This is content for my title pane</p>

And in 1.7 and above using the new html 5 data attributes:

  <div data-dojo-type="dijit.layout.TitlePane" data-dojo-props="title: 'hiya dude'">
     <p>This is content for my title pane</p>

So, where's the pain?

Ok, so a couple of problems exist for me when trying to RIA-ize a Roo application:

Dojo != Spring Javascript

The Dojo toolkit is under constant update We're on 1.7.2 in the community, and they are moving into mobile, HTML 5, media controls, etc. Spring Javascript embeds a custom build, and the most recent version isn't currently rolled out in Roo. In fact, I don't think there are plans (as far as I know) to upgrade Spring Javascript to 1.7.x, nor to update Roo. I will check with the Roo team to see what they are planning here.

People coding in Javascript shouldn't try to hide it. I'm not yet a fan of CoffeeScript or other frameworks that hide those things from you, because I think Javascript is such as quirky animal that dealing with it directly is probably better than not dealing with it, or working behind a veil.

Dojo is in transition

Because it was old, I decided to upgrade to Dojo 1.7. I gave up after a day because Dojo is transitioning to a new, bitchin' ARM (dynamic loading module system) that looks to be the bee's knees. Keep your eye on Dojo once this gets fully documented. They have curation, they have a consistent movement forward, active IRC channel, etc., and so I think they will really have a nice product here. However, I can't understand it, know the 1.6 and below model, and the documentation is not updated completely. So I was swimming in it.

We need a super-simple ui mechanism for Roo apps

I'm sorry, but I'm a minimalist. If I don't need it, it's outta here. And the view technologies in Roo should be pluggable. I think we should be able to do commands like:

roo> web mvc riatags add --toolkit dojo|extJS|jqueryUI|jqueryMobile

Scaffolding is in the way

I also think the scaffolding in Roo should be forward-only. Let's face it, how many times do you really keep the scaffolded UI on? For an admin tool, sure. But for anything commercial, it just takes too much to unwind it.

In addition, I think the messages/properties localization should be optional, or at least 100% transparent to me. In other words, the div id is the full div id, the message id is the full message id, period. It NEEDS to be simpler.

Finally, if I decide to modify my view resolution system, move to straight JSPs and ignore any bi-directional sync, I want Roo to keep hands off. I'll have to post a JIRA on this, but I think I ran into trouble where Roo adjusted my webmvc-config.xml file settings if I removed a few things once I tried to scaffold again. No biggie as I'm sure this isn't something planned on, but I think the bi-directionalness is great in the code layer, but not in the UI.

You seem tired

It's gonna be dawn soon and I'm thinking too much. I am really keen on moving Roo forward and working with the team to help set the agenda for Roo 1.3. All of this is adjustable by writing Roo add-ons and some minor adjustments to the current ones. And Roo saved me many hours on this project so far, and it will continue to do so.

So, big mouth, what have YOU been doing?

If you look in the GitHub repository, you'll see that I'm building a (currently AWFUL LOOKING) Dojo interface at /quizinator/admin/moderator. That controller does Ajax JSON request handling, and the index view is a small tab-container Dojo application.

More on this when I've had sleep and have implemented more. I may keep the actual quiz-taker UI in Spring Web Flow, and use Dojo for some Ajax there. But I like having a moderator tool that is a true Javascript client.


Quizzo in Roo case of the Mondays. Or, how you can be a JPA doofus 

This morning I took a look at my schema, and started to cry. Well, not really, but in that way people say LOL, I say COL. Here was my original schema (click to view the picture in full resolution):

Wait, this guy knows JPA? Sure he does!

Now, I know some of you have my back here. You say, "look, JPA can be confusing, you have to work with it." The thing is, I wrote a bloody chapter on JPA relationships, I teach JPA, my head just wasn't in the game, OK?

Just kidding. You know by now I'm razzing you all...

Anyhoo, I didn't bother taking any time to pay attention to my relationships (sounds like somebody's going to have cold soup for dinner). Turns out, I was abusing my @JoinColumn and mappedBy settings.

How to do a bi-directional one-to-many relationship

Do it up, Rimp. Here's how. First off, you need to define your one-sided entity and allow it to contain your Set (don't get me started about alternative options for collection types, that'll take us all day):

public class Quiz {

    @Size(max = 200)
    private String title;

    @Size(max = 500)
    private String description;

    @OneToMany(mappedBy = "quiz",
        cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<Question> questions = new HashSet<Question>();


Now, I know we're all adults in here, so that's why I put the harder stuff in the cabinet. You see, there are several key items of critical information here:

  • The collection is of type Set, and I'm creating a prototype (for new entities before I save them) of the real type of HashSet. Don't assume they will be HashSet instances when you fetch them again, they likely could be proxies that hydrate when you touch them (wear coding gloves).
  • I've decided to use the cascade option to tell JPA to cascade changes to the questions if I persist or update (merge) the quiz.
  • The mappedBy element is all-important. This tells us that the property pointing back to our Quiz instance in the class named Question will be called quiz. This establishes what side owns the relationship. As one of my students once said, "if you see mappedBy, it means this class does NOT own the relationship." Good rule to live by.

Whew! I'm feeling weak and dizzy. A lot of information hiding in there. Let's look at the Question class for the other side of this thing:

public class Question {
  @JoinColumn(name = "quiz_id")
  private Quiz quiz;

Wow, that's it??? Huh. Ok, well erm let's give this a shake. This class is in charge of the relationship, meaning that if it is touched, it will handle the insert or update of the foreign key. So:

  • The quiz variable name matches the mappedBy element in the Quiz table. Think of this as the role of the relationship. You may use the same table twice with different roles (think sourceAccount, destinationAccount and you get the idea. They would each have different @OneToMany relationships with different mappedBy elements, thereby different roles and variables.
  • The foreign key column that handles the database relationship is called quiz_id, and so we'll get a table called Question with a foreign key in it called quiz_id

Easy, peasy! Now, if you look at the relationship between Question and Quiz in the image above, it looks like there are three tables. But in the one below, the relationships are all simplified. That's because I paid attention to @JoinColumn and mappedBy. Click the image to see the full copy:

Mmmm... Low fat data models. Delicious and 1/2 the tables of your normal schema.

What else did I change recently?

I also got the state machine 99% working, with just a hitch on the test that determines whether the quiz is over or not. I'll work on that one tonight, now that I can actually understand my data model without getting sick to my stomach.

I moved the QuizRunState tracking state into memory, as it was failing me. Oh, one more thing - don't assume that IntelliJ catches Java Language assert statements. I was guarding my code with assertions to catch any invalid states in the state machine. Turns out, Maven turns on assertion checking when testing but IntelliJ does not. I'm not talking about JUnit assertions, but the Java System assertion language statement, such as I use in this fragment of QuizRunStateMachineInMemory:

  public void startQuiz() {
    assert (runState == QuizRunState.NOT_STARTED);
    runState = QuizRunState.IN_PROGRESS;

Oh, it burns us baggins! To fix this, you edit your JUnit runner and add the -ea -esa flags to your vm settings. And, ladies and gentlemen, that was the reason I was getting errors in my Maven code that weren't showing up in IntelliJ. Just sayin'

See ya tomorrow (or maybe later tonight).


Quizzo Saturday - testing web flows

GitHub commit URLs: 82add3e1e23eee8b84058c12fcd6ff211f70096e and more importantly, 4cfed580c3404e61d501ac4ee0182c294b1b0b89

Ok, this is kind of a tangent. But I wanted to really debug the flow logic for these interactions, and better understand the flow logic itself before I bother to write up nice looking views.

Test that our flow starts with the correct state

I started with this first step, which is pretty easy to test:

<var class="" name="teamSetupForm"/>

<view-state id="register-team" view="playQuizzo/register-team"
    <transition on="continue" 
                bind="true" validate="true"/>

This state fills in a portion of the teamSetupForm flow-scoped variable. How do we test this? Somewhat easily. First, we start by building a test that is a subclass of AbstractXmlFlowExecutionTests:

public class QuizzoFlowTest extends AbstractXmlFlowExecutionTests {

  protected FlowDefinitionResource getResource(
               FlowDefinitionResourceFactory resourceFactory) {

    return resourceFactory.

Next, we have to build a method to expose a stub version of our Web Flow Spring Bean, the QuizzoFlowManager. It's referred to in the rest of the flow as quizzoFlowManager. This stub will replace our Spring Bean, and will provide access to any methods the flow calls. The flow execution engine may throw errors if it looks for this bean while parsing the form. So, we add this method to the test:

protected void configureFlowBuilderContext(
               MockFlowBuilderContext builderContext) {

  StubQuizzoFlowManager stubQuizzoFlowManager = 
                        new StubQuizzoFlowManager();


This method is called once we execute any flow start or resume methods in our mock flow engine.

Writing a flow test

Consider the test code below:

public void testStartFlow() {
  MutableAttributeMap map = new LocalAttributeMap();
  MockExternalContext context = new MockExternalContext();
  startFlow(map, context);
  TeamSetupForm form = (TeamSetupForm) getFlowScope().get("teamSetupForm");

The test does the following things:

  • Sets up a attribute map, required for starting a flow. This is just a property map.
  • Builds a fake Flow context, also required when launching a flow.
  • Calls the base test class's startFlow method, which launches the flow.
  • Checks to make sure that the flow is waiting on the register-team view state.
  • Checks to make sure the Web Flow engine creates the variable, teamSetupForm in the var webflow tag.
  • Checks to make sure the form is not null.

But what about checking events? For that, we'll push a "continue" event, and set the values that the form would have submitted in our Form bean:

public void testSubmitTeamName() {
  MockExternalContext context = new MockExternalContext();

      createTeamSetupForm("The Jets", "When you're a Jet you're a Jet"));


In this test, we start with the flow sitting on the register-team state. Since Web Flow is not running any states before our unit test, we have to create our teamSetupForm ourselves, and set the value of it using a helper method to include the team name and team message.

We then tell the context to send the continue event, and resume our flow. We check once this completes to make sure we are now sitting on the register-team-members state.

A more complex example

Now we are going to test the next state and its transition to the following state using continue:

<view-state id="register-team-members" view="playQuizzo/register-team-members"

  <transition on="continue" to="ready-to-play" bind="true" validate="true">
      <evaluate expression="quizzoFlowManager.saveTeamData(flowRequestContext)"/>
  <transition on="add-team-member"/>
  <transition on="remove-team-member"/>
  <transition on="back" to="register-team"/>

<action-state id="ready-to-play">
  <evaluate expression="quizzoFlowManager.pollReady(flowRequestContext)"/>
  <transition on="yes" to="play-round"/>
  <transition on="poll" to="poll"/>

You may think this test executes just fine:

public void testSubmitTeamMembers() {

  MockExternalContext context = new MockExternalContext();
      createTeamSetupForm("The Jets",
              "When you're a Jet you're a Jet",
      "Ice", "Action", "Baby John", "Tiger", "Joyboy"));


But it fails on the state assertion. It states that the state is actually play-round. How can this be?

Action States

This is because we're using an action state from our web flow. Action states do not wait on anything. They immediately execute their evaluations, and take action from their responses. I knew this when building the flow, but scanned by it when writing the test. Ugh.

How did I figure this out? You'd think by closely reading the ready-to-play state definition, but no... Instead, I amped up the logging for the webflow framework by setting this entry in

This rewarded me with a great amount of useful detail:

2012-02-25 12:19:47,032 [main] DEBUG org.springframework.webflow.engine.impl.FlowExecutionImplFactory - Creating new execution of 'flow'
2012-02-25 12:19:47,047 [main] DEBUG org.springframework.webflow.engine.impl.FlowExecutionImpl - Resuming in org.springframework.webflow.test.MockExternalContext@1494cb8b
2012-02-25 12:19:47,054 [main] DEBUG org.springframework.webflow.engine.Flow - Restoring [FlowVariable@3209fa8f name = 'teamSetupForm', valueFactory = [BeanFactoryVariableValueFactory@2d20dbf3 type = TeamSetupForm]]
2012-02-25 12:19:47,072 [main] DEBUG org.springframework.webflow.engine.ViewState - Event 'continue' returned from view [MockViewFactoryCreator.MockView@3e0d1329 viewId = 'playQuizzo/register-team-members']
2012-02-25 12:19:47,074 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Executing [EvaluateAction@2326a29c expression = quizzoFlowManager.saveTeamData(flowRequestContext), resultExpression = [null]]
2012-02-25 12:19:47,074 [main] DEBUG org.springframework.webflow.execution.AnnotatedAction - Putting action execution attributes map[[empty]]
2012-02-25 12:19:47,084 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Finished executing [EvaluateAction@2326a29c expression = quizzoFlowManager.saveTeamData(flowRequestContext), resultExpression = [null]]; result = success
2012-02-25 12:19:47,085 [main] DEBUG org.springframework.webflow.engine.Transition - Executing [Transition@3a4c5b4 on = continue, to = ready-to-play]
2012-02-25 12:19:47,085 [main] DEBUG org.springframework.webflow.engine.Transition - Exiting state 'register-team-members'
2012-02-25 12:19:47,086 [main] DEBUG org.springframework.webflow.engine.ActionState - Entering state 'ready-to-play' of flow 'flow'
2012-02-25 12:19:47,086 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Executing [EvaluateAction@36afae4a expression = quizzoFlowManager.pollReady(flowRequestContext), resultExpression = [null]]
2012-02-25 12:19:47,086 [main] DEBUG org.springframework.webflow.execution.AnnotatedAction - Putting action execution attributes map[[empty]]
2012-02-25 12:19:47,087 [main] DEBUG org.springframework.webflow.execution.AnnotatedAction - Clearing action execution attributes map[[empty]]
2012-02-25 12:19:47,087 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Finished executing [EvaluateAction@36afae4a expression = quizzoFlowManager.pollReady(flowRequestContext), resultExpression = [null]]; result = yes
2012-02-25 12:19:47,088 [main] DEBUG org.springframework.webflow.engine.Transition - Executing [Transition@47db9852 on = yes, to = play-round]
2012-02-25 12:19:47,088 [main] DEBUG org.springframework.webflow.engine.Transition - Exiting state 'ready-to-play'
2012-02-25 12:19:47,088 [main] DEBUG org.springframework.webflow.engine.ViewState - Entering state 'play-round' of flow 'flow'
2012-02-25 12:19:47,088 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Executing [EvaluateAction@21ed5459 expression = quizzoFlowManager.setupQuestionAndChoices(flowRequestContext), resultExpression = [null]]
2012-02-25 12:19:47,089 [main] DEBUG org.springframework.webflow.execution.AnnotatedAction - Putting action execution attributes map[[empty]]
2012-02-25 12:19:47,090 [main] DEBUG org.springframework.webflow.execution.AnnotatedAction - Clearing action execution attributes map[[empty]]
2012-02-25 12:19:47,090 [main] DEBUG org.springframework.webflow.execution.ActionExecutor - Finished executing [EvaluateAction@21ed5459 expression = quizzoFlowManager.setupQuestionAndChoices(flowRequestContext), resultExpression = [null]]; result = success
2012-02-25 12:19:47,091 [main] DEBUG org.springframework.webflow.engine.impl.FlowExecutionImpl - Assigned key 1
2012-02-25 12:19:47,091 [main] DEBUG org.springframework.webflow.engine.ViewState - Rendering + [MockViewFactoryCreator.MockView@643cb075 viewId = 'playQuizzo/play-round']
2012-02-25 12:19:47,092 [main] DEBUG org.springframework.webflow.engine.ViewState -   Flash scope = map[[empty]]
2012-02-25 12:19:47,092 [main] DEBUG org.springframework.webflow.engine.ViewState -   Messages = [DefaultMessageContext@4c6504bc sourceMessages = map[[null] -> list[[empty]]]]
2012-02-25 12:19:47,092 [main] DEBUG org.springframework.webflow.engine.Transition - Completed transition execution.  As a result, the new state is 'play-round' in flow 'flow'
2012-02-25 12:19:47,093 [main] DEBUG org.springframework.webflow.engine.Transition - Completed transition execution.  As a result, the new state is 'play-round' in flow 'flow'

If you spend time reading this, you'll see two flow state executions - one for the view state, and one for the action state. Our stub class returns "yes" from our transition in the poller state, and so we move to the next view state, play-round


Testing in WebFlow is rather difficult, because of the number of mock objects, the complexity of flow logic, and the fact that it's in XML, which is not compiled and therefore really requires tests. But is is worth it, as long as you're not using this as an excuse to test your beans themselves. You should test those either in unit or Spring integration tests. My assertions are mostly around making sure we submitted the right events to trigger the right view states.

Next I'll be wiring up some pages to these flow view states, and starting to really get the processing going. I'm also going to start writing an admin page to control the game itself and provide an audience view.