JPz'log Coin Coin and Plop da Plop

17Jun/090

IzPack 4.3.1 is available

I'm pleased to let the world know of the availability of IzPack 4.3.1 :-)

This is a maintenance release. While it is not very spectacular by itself, upgrading is still a very good idea as you will grab a few fixes there and there.

Many thanks to our community (developers, contributors, issue reporters and users) for making this release possible, and go to http://izpack.org to get your copy today!

Filed under: English, IzPack, Java No Comments
11Jun/090

Support the IzPack development by making a donation!

Hi everyone,

As you can easily guess, maintaining and developing IzPack since 2001 has been a lot of fun... and also a significant time investment :-)

I am already offering professional services for those who would need support, consulting and custom developments (see http://izpack.proservices.ponge.info/). A few companies also give back to the project in the form of patches and contributors / developers: thanks to you all!

However, the large majority of IzPack users simply download it and never give back anything. This is perfectly fine of course, but I would like to let you know that you can support my very own work on this project by making a donation :-)

To do that, you can use the following link (note that you will receive both my gratitude AND a true invoice).


Thanks for your support!

(ps: for those who may ask, the adsense units on the website mainly cover the domain name and web hosting)

Filed under: English, IzPack No Comments
1Jun/090

Discovering Grails Web Flows

I recently discovered Grails Web Flows. This is basically a Groovy DSL on top of Spring Web Flows.

I did a quick dirty and imperfect example which is a number guessing game. I took inspiration from another Grails Web Flows tutorial.

In this post, I will limit myself to some very quick description of web flows, and I urge you to read the documentations (from Grails and Spring). The idea behind web flows is to provide a framework for web conversations that span multiple HTTP requests, such as wizards, payment processes and such. A "web flow" is modeled as a state machine, where:

  • states represent either an action (i.e., some code) or a view, and
  • transitions are triggered based on the outcome from the state, which is a simple string.

As such, web flows free the developer from much repetitive logic when you need to control states of a web conversation.

In this example, the number to guess is 25 (we could have made it non-static, but who cares?). The user has 5 attempts. The corresponding flow is:

flow

Grails provides web flows out of the box. All you have to do is to create a special controller closure property which ends by "Flow":

class GuessController
{
 
  def toGuess = "25"
 
  def index = {
    redirect(action: "guess")
  }
 
  def guessFlow = { ... }
 
}

We now have to define the "guess" flow. As often in Groovy and Grails, it boils down to some intuitive builder structure:

class GuessController
{
 
  def toGuess = "25"
 
  def index = {
    redirect(action: "guess")
  }
 
  def guessFlow = {
 
    start {
      action {
        [guessLeft: 5]
      }
      on("success").to("ask")
    }
 
    ask {
      on("evaluate").to("evaluate")
    }
 
    done()
 
    fail()
 
    evaluate {
      action {
        if (params.number == toGuess)
        {
          return yes()
        }
        flow.guessLeft = flow.guessLeft - 1
        if (flow.guessLeft == 0)
        {
          return loose()
        }
        else
        {
          return no()
        }
      }
      on("yes").to("done")
      on("no").to("ask")
      on("loose").to("fail")
    }
  }
}
  1. start is an action state, which is called first, and that puts a guessLeft variable in the flow context.
  2. The ask state displays a web page, then delegates the logic to the evaluate action state.
  3. The evaluate action state either pushes the flow to the final states, or loops back to the ask state if there are guesses left.
  4. done and fail are final states that just show some web pages.

Finally there are 3 views that you need to create. Since the web flow is named "guess", they must be in a special "guess" subfolder of the matching controller views. Also, they must be named by the state names.

ask.gsp

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
  <head><title>Simple GSP page</title></head>
  <body>
 
  <g:javascript library="prototype"/>
  <g:javascript>
    document.observe("dom:loaded", function() {
      $("field").focus();  
    });
  </g:javascript>
 
  <h1>Guess</h1>
  <p>Guesses left: <strong>${guessLeft}</strong>.</p>
 
  <p>
    <g:form action="guess">
      <g:textField id="field" name="number" value="0" />
      <g:submitButton name="evaluate" value="Try this number!" />
    </g:form>
  </p>
 
  </body>
</html>

Note that the guessLeft flow context variable is available directly in the GSP. Also, note that the form action must match the web flow name and that the submit button name is the outcome of the view state.

done.gsp

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
  <head><title>Simple GSP page</title></head>
  <body>You won!</body>
</html>

fail.gsp

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
  <head><title>Simple GSP page</title></head>
  <body>You failed...</body>
</html>
   

JPz'log is Digg proof thanks to caching by WP Super Cache