<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Transentia &#187; Groovy</title>
	<atom:link href="http://wordpress.transentia.com.au/wordpress/tag/groovy/feed/" rel="self" type="application/rss+xml" />
	<link>http://wordpress.transentia.com.au/wordpress</link>
	<description>transentia pty. ltd.; development, consulting, training at the leading-edge of technology</description>
	<lastBuildDate>Thu, 17 Jun 2010 10:08:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Another GroovyMag &#8216;Masterpiece&#8217;: Gambling on Griffon And Grails Going Gangbusters</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/05/10/another-groovymag-masterpiece-gambling-on-griffon-and-grails-going-gangbusters/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/05/10/another-groovymag-masterpiece-gambling-on-griffon-and-grails-going-gangbusters/#comments</comments>
		<pubDate>Mon, 10 May 2010 00:03:35 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Griffon]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=926</guid>
		<description><![CDATA[Another GroovyMag article. 
Should stop the other ones from feeling lonely!
Somehow, the zip bundled with the article didn&#8217;t have the full sources&#8230;don&#8217;t know what happened. My apologies to all who tried to find them.
Never mind, here they are. 
Maybe its a case of &#8220;Better Late Than Never&#8221;? Or &#8220;All Good Things Come To Those Who [...]]]></description>
			<content:encoded><![CDATA[<p>Another <a href="http://www.groovymag.com/">GroovyMag</a> article. </p>
<p>Should stop <a href="http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/">the</a><a> </a><a href="http://wordpress.transentia.com.au/wordpress/2010/02/03/batch-processing-with-spring-batch/">other</a> <a href="http://wordpress.transentia.com.au/wordpress/2010/02/04/the-groovy-internet-mood-meter-in-svg/">ones</a> from feeling lonely!</p>
<p>Somehow, the zip bundled with the article didn&#8217;t have the full sources&#8230;don&#8217;t know what happened. My apologies to all who tried to find them.</p>
<p>Never mind, <a href='http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/Gr3.zip'>here they are</a>. </p>
<p>Maybe its a case of &#8220;Better Late Than Never&#8221;? Or &#8220;All Good Things Come To Those Who Wait&#8221;?</p>
<p>Enjoy!</p>
<hr />
<p><strong>Gr3</strong></p>
<p>Gambling on Griffon and Grails Going Gangbusters</p>
<p>Bob Brown</p>
<p>bob@transentia.com.au</p>
<p>http://www.transentia.com.au</p>
<p><em>The Grails and Griffon frameworks both strive to the same end: to bring the goodness of </em>Convention over Configuration<em> to your life. Individually, they are excellent technologies but when working together using the REST architectural pattern they can enable you to achieve great things.</em></p>
<h1>A Brief Overview</h1>
<p>They go by many names: ‘Pokies’, “one-armed bandits”, “slot machines”, “fruit machines” and even “video gaming terminals.” Some call them good clean fun and harmless entertainment; others denounce them as scourges on society, preying on those members least able to afford feeding them. Governments are addicted to the tax they generate, and big business gets bigger profits from them each year. Socially-minded campaigners regularly call for them to be banned and in an attempt to minimize their negative impact on his clientele, Russell “The (Social) Gladiator” Crowe took the unusual step of removing them from the clubhouse when he invested in his favorite Australian football team—the Sydney Rabbitohs—in 2007.</p>
<p>Given all this controversy, and also given my desire to explore the wonderful REST-ful world of Griffon and Grails, what else could I do but risk the ire of Russell and the many Rabitohs supporters and build a pokie (albeit very simple and cashless) of my very own!</p>
<p>Figure 1 shows Gr3, the “Griffon, Grails and Groovy Pokie Machine.”</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_1.png" alt="figure_1" title="figure_1" width="330" height="750" class="alignnone size-full wp-image-933" /><br />
<em>Figure 1: The Gr3 Client Application</em></p>
<p>As the name suggests, this is a Griffon desktop application that talks to a Grails backend application. Griffon provides a REST plugin and Grails has native support for REST, so developing REST-style interactions is especially easy.</p>
<p>The Gr3 application is simple to use: select an amount to play with and press the ‘Play’ button. If lady luck deigns to smile on you, you will win. More likely, the heartless random number generator underlying things will more than happily conspire to take your ‘money’ from you. The application displays a number of regularly-updating interesting statistics, most notably the overall totalizer value which reflects the total amount of money in the server’s ‘pot’ at any instant [1]. Each instance of Gr3 will add to and take money from this single pot as gameplay continues. There is also a simple preferences configuration GUI.</p>
<p>This application uses the “hot off the press” Grails 1.2.0-RC-1 and Griffon 0.3-SNAPSHOT versions.</p>
<h1>REST-Style Interactions</h1>
<p>REST defines a set of architectural principles for designing simple HTTP-oriented Web services. These principles are:</p>
<ul>
<li>Make proper use of the various defined HTTP methods</li>
<li>Expose all services as stateless services; assume that the client best knows how to manage its own state</li>
<li>Expose directory structure-like URIs that uniquely identify interesting or useful resources</li>
<li>Transfer data in structured form amenable to further processing using technologies such as XML, JSON (JavaScript Object Notation) or YAML (YAML Ain’t Markup Language)</li>
</ul>
<p>REST is increasingly popular and is on its way to becoming a dominant technology due to its fundamental simplicity (especially when compared to the alternative [but more comprehensive] SOAP/XML-based ecosystem).</p>
<p>Figure 2 shows the REST-style interactions that take place between the Gr3Client and Gr3Server. Although the actual sequence is quite simple, there are some guiding rules that I have adopted:</p>
<ul>
<li>The register and unRegister operations are treated akin to Create and Delete and (as prescribed by REST) use the HTTP POST and DELETE methods. They return a plain text status string.</li>
<li>The play and win operations are treated as Update and so use the HTTP PUT method. They return a JSON object containing the most-up-to-date totalizer value.</li>
<li>The totalizer operation is purely idempotent [2] and so uses HTTP GET.</li>
</ul>
<p>While these principles may not be in keeping with a purist approach to REST, they are still quite appropriate and allow me to demonstrate various aspects of REST in Griffon and Grails. In any case, the pure REST approach is more focussed on CRUD [3] update of network accessible resources than dealing with the more process-oriented service such as we have with Gr3Server.</p>
<p>This may sound rather complex but you will soon see that the support built into Grails and Griffon makes it all as easy as losing your shirt in Las Vegas. Figure 2 shows that the interaction between the Gr3Client and Gr3Server is really quite simple.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_2.png" alt="figure_2" title="figure_2" width="482" height="555" class="alignnone size-full wp-image-938" /><br />
<em>Figure 2: Sequence Diagram Showing the Simple Interactions between Gr3Client and Gr3Server</em></p>
<h1>The ‘Gr3Server’ Grails WebApp</h1>
<p>This is the simpler of the two applications. It is made up of a single TotalizerController class, with a little bit of supporting code thrown in.</p>
<p>Let’s get started.</p>
<p>Listing 1 shows the TotalizerController class in its entirety [4].</p>
<pre>
package gr3

class TotalizerController {
  private static final JSON_CT = "application/json"
  private static final TEXT_CT = "text/plain"
  def totalizerService
  def clientRegistryService
  static allowedMethods =
    [startAction: 'POST', stopAction: 'DELETE',
     playAction: 'PUT', winAction: 'PUT',
     totalizerAction: 'GET']
  def beforeInterceptor = {
    def remIp = request.remoteAddr
    def registered = clientRegistryService.registered(remIp)
    if (registered &amp;&amp; (actionName == 'registerAction')) {
      log.warn "Incoming register request from registered client: $remIp"
      return false
    }
    else if ((! registered) &amp;&amp; (actionName == 'unRegisterAction')) {
      log.warn "Incoming unRegister request from unregistered client: $remIp"
      return false
    }
  }
  def registerAction = {
    def remIp = request.remoteAddr
    log.debug "Register: $remIp"
    clientRegistryService.register(remIp)
    render(text: "OK", contentType: TEXT_CT)
  }
  def unRegisterAction = {
    def remIp = request.remoteAddr
    log.debug "UnRegister: $remIp"
    clientRegistryService.unRegister(remIp)
    render(text: "OK", contentType: TEXT_CT)
  }
  def totalizerAction = {
    log.debug "totalizerAction request from ${request.remoteAddr}"
    render(contentType: JSON_CT) {
      [tote: totalizerService.getCurrentValue()]
    }
  }
  def playAction = {
    def amt = params.int('amount')
    def tote = totalizerService.accumulate(amt)
    log.debug "playAction request from ${request.remoteAddr}: ${amt}; tote now: ${tote}"
    render(contentType: JSON_CT) {
      [tote: tote]
    }
  }
  def winAction = {
    def playValue = params.int('playValue')
    def winnings = params.int('winnings')
    def tote = totalizerService.accumulate(-winnings)
    log.debug
      "winAction request from ${request.remoteAddr}: *** WIN *** played: ${playValue}, won: ${winnings}; tote now: ${tote}"
    render(contentType: JSON_CT) {
      [tote: tote]
    }
  }
}
</pre>
<p><em>Listing 1: the Main TotalizerController class</em></p>
<p>This code is quite unremarkable. There are only a few points of interest, the first of these being the allowedMethods map. This is a standard facility in Grails that makes it possible to restrict how a given action closure may be invoked. I have shown it here because it also helps make the correspondence between the code and my guiding rules for the REST interactions in this application clear.</p>
<p>A second point of interest concerns TotalizerController’s reliance on two injected services. The TotalizerService (shown in Listing 2) is basically an extremely simple wrapper for an AtomicInteger, which represents the instantaneous accumulated value of the global totalizer. The use of AtomicInteger, which is inherently thread safe, keeps the coding for the shared singleton service clean and clear and free from nasty synchronized blocks.</p>
<pre>
[…elided…]

class TotalizerService {
  boolean transactional = false
  private final tote = new AtomicInteger()
  def getCurrentValue = { tote.get() }
  def accumulate = {amt -&gt; tote.addAndGet(amt) }
}
</pre>
<p><em>Listing 2: the TotalizerService class</em></p>
<p>The third major point of interest in TotalizerController is the injected ClientRegistryService (shown in Listing 3).</p>
<pre>
[…elided…]

class ClientRegistryService implements InitializingBean {
  def authorisedIPs
  def clientRegistry
  boolean transactional = false
  def register = {ip -&gt; clientRegistry[ip] = true }
  def registered = {ip -&gt; clientRegistry[ip] == true }
  def unRegister = {ip -&gt; clientRegistry[ip] = false }
  void afterPropertiesSet() {
    def authorisedMap = [:]
    for (ip in authorisedIPs)
      authorisedMap[ip] = false
    clientRegistry = authorisedMap.asSynchronized()
  }
}
</pre>
<p><em>Listing 3: the ClientRegistryService class</em></p>
<p>ClientRegistryService is concerned with providing a simple veneer of security; it maintains a list of IP addresses and enforces the rule that only one client may be present at any given IP address. As shown in Figure 2, a client registers itself at startup and unregisters at shutdown.</p>
<p>ClientRegistryService relies on having a configured list of IP address injected into it via the authorisedIPs local variable. It will restrict access to those clients only and will also maintain the connected status of these clients. To achieve this operational rule, the service is defined to be an InitializingBean. This means that the underlying Spring Framework infrastructure will call into the defined afterPropertiesSet method after it has created the service instance and subsequently injected any needed resources into that instance. The afterPropertiesSet method examines the injected authorisedIPs list and constructs a client status map according to the list’s contents.</p>
<p>The authorisedIPs list is configured externally to the service via Grails’ conf/spring/resources.groovy file, as shown in Listing 4.</p>
<pre>
beans = {
  xmlns util: "http://www.springframework.org/schema/util"

  util.list(id: 'authorisedIPs') {
    value '127.0.0.1'
  }
}
</pre>
<p><em>Listing 4: resources.groovy, showing the Configuration of the authorisedIPs List</em> </p>
<p>Note that this is a slightly ‘artificial’ example: for ‘real’ production-quality code I could (and probably should) have easily defined and initialized the actual requisite clientRegistry map instance via resources.groovy; this path gave me a chance to introduce the useful InitializingBean facility though, so please forgive my slightly roundabout coding.</p>
<p>It is important that access to the clientRegistry be synchronized to guard against wayward concurrent update. The authorisedMap.asSynchronized() expression achieves this.</p>
<p>TotalizerController generally invokes the clientRegistryService from within its beforeInterceptor closure. This gives a single point of control for the access checks and helps keep the controller code DRY [5].</p>
<h2><em>REST-Style URL Mappings</em></h2>
<p>It is slightly “bad form” to directly expose the names of the underlying controller actions to the client application; doing so results in fragile code that potentially cannot be changed without affecting the client. Since “fearless change” is one of the basic tenets of Agile development, I have established a series of indirect mappings in conf/URLMappings.groovy. This is shown in Listing 5.</p>
<pre>
class UrlMappings {
  static mappings = {
    "/totalizer/play"(controller:"totalizer",
      action: 'playAction', parseRequest:true)
    "/totalizer/win"(controller:"totalizer",
      action: 'winAction', parseRequest:true)
    "/totalizer/register"(controller:"totalizer",
      action: 'registerAction')
    "/totalizer/unRegister"(controller:"totalizer",
      action: 'unRegisterAction')
    "/totalizer/totalizer"(controller:"totalizer",
      action: 'totalizerAction')
  […elided…]
  }
}
</pre>
<p><em>Listing 5: REST URL Mappings</em></p>
<p>Of interest here is the way that the mappings for play and win also enable Grails’ automatic JSON-parsing behavior.</p>
<h1>The ‘Gr3Client’ Griffon Desktop Application</h1>
<p>The client side portion of the pokie application is quite a lot bigger than the server-side portion that we have just examined. This is to be expected: GUI handling code is often quite involved and the client contains a fair bit more functionality.</p>
<h2><em>The Main Application MVGGroup</em></h2>
<p>Every Griffon application consists of one or more groups of Model, View and Controller (called, naturally enough, an MVCGroup). In this section we’ll take a look at the main MVG group; this is what produces the portion of the GUI shown in Figure 1.</p>
<p>The underlying model is quite straightforward, as Listing 6 (excerpted) shows.</p>
<pre>
import groovy.beans.Bindable
class Gr3ClientModel {

  […elided…]

  @Bindable String playedValue = '$0'
  @Bindable Integer plays = 0
  @Bindable Boolean playButtonEnabled = true
}
</pre>
<p><em>Listing 6: the Main MVCGroup’s Model Class</em></p>
<p>There is an @Bindable property for each value displayed in the view, as well as a property defining the state of the play button. The @Bindable annotation invokes an AST transformation [6] that wraps up the PropertyChangeSupport facility that all Swing developers have learned to know and love.</p>
<p>The application’s main view (shown in part in Listing 7) makes good use of Griffon’s ‘UberBuilder’ to allow a view to be created using features from several underlying libraries (in this case, Swing and SwingX [7])</p>
<pre>
[…elided…]

def leftReelIcons = [imageIcon('/reel/card_figures_-_club_01.png'),
        imageIcon('/reel/card_figures_-_diamond_01.png'),
        imageIcon('/reel/attenzione_rotondo_archi_01.png'),
        imageIcon('/reel/card_figures_-_heart_01.png'),
        imageIcon('/reel/card_figures_-_spade_01.png')]
def middleReelIcons = (leftReelIcons[2..-1] + leftReelIcons[0..1])
def rightReelIcons = (middleReelIcons[2..-1] + middleReelIcons[0..1])
def reelIcons = [left: leftReelIcons,
                 middle: middleReelIcons, right: rightReelIcons]
application(title: 'Gr3Client',
        size: [320, 740],
        resizable: false,
        defaultCloseOperation: WindowConstants.DO_NOTHING_ON_CLOSE,
        windowClosing: controller.exitAction,
        locationByPlatform: true,
        […elided…]) {
  menuBar(mainMenuBar)
  vbox(constraints: NORTH) {
    jxheader(title: "Gr3",
            description:
              'Pokie Machine using Griffon, Grails and Groovy.',
            icon: imageIcon('/griffon-icon-48x48.png'),
            border: emptyBorder(4),
            titleForeground: Color.RED,
            backgroundPainter: new PinstripePainter(Color.LIGHT_GRAY)
    panel() {
      tableLayout(cellpadding: 4) {
        tr {
          td(align: 'left') {
            label('Plays:')
          }
          td(align: 'right') {
            label(id: 'plays', text: bind { model.plays})
          }
          td(align: 'left') {
            label('Played:')
          }
          td(align: 'right') {
            label(id: 'played', text: bind { model.playedValue})
          }
        }
        tr {
          td(align: 'left') {
            label('Earnings:')
          }
          td(align: 'right') {
            label(id: 'earnings', text: bind { model.earnings})
          }
          td(align: 'left') {
            label('Totalizer:')
          }
          td(align: 'right') {
            label(id: 'totalizer',
                  text: bind { model.totalizerValue})
          }
        }
      }
    }
  }
  panel(new Spindle(), id: 'spindle',
        border: loweredBevelBorder(), constraints: CENTER) {
    borderLayout()
    tableLayout(cellpadding: 4) {
      tr {
        for (reel in ['left', 'middle', 'right']) {
          td(align: 'center') {
            widget(id: "${reel}Reel".toString(),
                   new Reel(icons: reelIcons[reel]))
          }
        }
      }
    }
  }
  panel(constraints: SOUTH) {
    tableLayout(cellpadding: 4) {
      tr {
        buttonGroup(id: 'playValue').with {group -&gt;
          for (v in [1, 2, 5, 10, 20, 50])
            td {
              radioButton(text: "\$$v".toString(),
                          buttonGroup: group, selected: v == 20,
                          actionCommand: "$v".toString())
            }
        }
      }
      tr {
        td(colspan: 6, align: 'center') {
          label(id: 'message', text: bind { model.message })
        }
      }
      tr {
        td(colspan: 6, align: 'center') {
          button(playAction, id: 'playButton')
        }
      }
    }
  }
}
</pre>
<p><em>Listing 7: the Main MVCGroup’s View</em></p>
<p>The clean, declarative nature of Listing 7 is a thing of beauty to my eyes! For those of us who have dreams formatted into discrete pages marked up by HTML, Groovy’s tableLayout layout manager is A Good Thing indeed.</p>
<p>Of interest is the WindowClosing event handling. To allow the client to communicate with its server at shutdown time, custom exit-handling code is established in the application stanza. To allow the custom processing to work, it is important to ensure that conf/Application.groovy is edited with:</p>
<pre>
autoShutdown = false
</pre>
<p>Note the way the ‘playValue’ Button group is defined. This adopts Josh Reed’s tip for easing the creation of groups of mutually-exclusive radiobuttons. It’s worth taking a look at Josh’s site. See “Learn More” for the URL.</p>
<p>The Panel/Spindle teamup is also worth taking a look at. The documentation for the panel widget says: <em>“A javax.swing.JPanel is returned, unless the user passes in a subclass of JPanel as the value argument, in which case the value argument is returned.”</em> The Spindle class used here uses this oft-overlooked ability and is a ‘bog-standard’ class that extends JPanel so that the red ‘win’ line is painted across the panel and on top of the ‘reels.’</p>
<p>The use of SwingX painters is discussed in “A Little Gloss: SwingX Painters”, below.</p>
<p>The main MVCGroup’s controller contains very little ‘trickery’ and all the REST-related work is offloaded to an injected ServerService class, so (in the interest of saving space) it won’t be shown here. Various sections of the controller will be examined as this article continues.</p>
<h2><em>Additional Conventional Handling</em></h2>
<p>The Gr3Client application is not only comprised of models, view and controllers; there are actions, menus and services as well. Gr3Client takes advantage of Griffon’s conventional handling for these aretefacts in addition to the standard MVC conventional handling.</p>
<p>Griffon processes actions and menus if they are contained in eponymously-named directories under griffon-app. Figure 3 shows the Gr3Client’s resulting directory tree structure.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_3.png" alt="figure_3" title="figure_3" width="304" height="413" class="alignnone size-full wp-image-941" /><br />
<em>Figure 3: Additional Conventional Directories</em></p>
<p>It is also necessary to modify the entry for the MVCGroup in Application.groovy to be modified appropriately. For example:</p>
<pre>
'Gr3Client' {
  model = 'Gr3ClientModel'
  controller = 'Gr3ClientController'
  actions = 'Gr3ClientActions'
  menus = 'Gr3ClientMenus'
  view = 'Gr3ClientView'
}
</pre>
<p>Ordering is important in this definition: actions and menus are required to be processed first, since they are dependencies of the view.</p>
<p>In addition to making the code clearer, this feature also makes it slightly shorter. Consider this excerpt from actions/Gr3ClientActions.groovy:</p>
<pre>
action(id: 'playAction',
       name: 'Play',
       closure: controller.playAction,
       shortDescription: 'Play',
       enabled: bind { model.playButtonEnabled }
)
</pre>
<p>Normally, the list of actions would be required to be wrapped in an actions {} stanza. By using this facility, the actions wrapper is assumed. The same is true of any menus defined by an application.</p>
<p>Services can be placed in a services directory and are recognized and injected where needed ‘automagically.’</p>
<h2><em>Scheduling Periodic Updates</em></h2>
<p>The main view displays a global totalizer value that is continually updated. To achieve this, a ‘background’ instance of javax.swing.Timer is created during MVCGroup creation to periodically poll the Gr3Server and update the associated model value. As would be expected, the code is very simple and is excerpted in Listing 8.</p>
<pre>
import java.awt.event.ActionListener
import java.text.NumberFormat

class Gr3ClientController {

  […elided…]

  def serverService

  private static final nf = NumberFormat.getCurrencyInstance()
  def totalizerAction = {evt = null -&gt;
    doOutside {
      model.totalizerValue = nf.format(serverService.totalizerAction())
    }
  }
  void mvcGroupInit(Map args) {
    def timer = new javax.swing.Timer(1500, totalizerAction as ActionListener);
    timer.setInitialDelay(500);
    timer.start();

[…elided…]
</pre>
<p><em> Listing 8: Background Timer Handling</em></p>
<p>The totalizerAction closure is periodically executed by the timer in the context of Swing’s Event Dispatching Thread (EDT). To ensure that the GUI remains responsive, the closure performs its time-consuming communications, formatting and model update operations outside of the EDT. In a traditional Swing application, threading is quite awkward but the Groovy/Griffon SwingBuilder DSL makes life much easier.</p>
<p>Further points of interest in Listing 8 include the use of the standard Java java.text.NumberFormat facility to enable currency formatting, and Groovy’s powerful capability that enables the totalizerAction closure to be coerced to an instance of java.awt.event.ActionListener, which is what the Timer instance requires.</p>
<h2><em>The ‘PrefsPanel’ MVCGroup</em></h2>
<p>In addition to the main application MVCGroup, Gr3Client has an additional PrefsPanel MVCGroup accessible via the File-&gt;Preferences menu. This simple dialog is shown in Figure 4.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_4.png" alt="figure_4" title="figure_4" width="352" height="232" class="alignnone size-full wp-image-944" /><br />
<em>Figure 4: the Preferences MVCGroup Dialog</em></p>
<p>As Listing 9 shows, the model portion of the dialog’s MVC triumvirate is straightforward; the model is simply a value and associated validity flag for each textfield.</p>
<pre>
import groovy.beans.Bindable

class PrefsPanelModel {
  @Bindable String server = PrefsUtils.getServer()
  @Bindable String port = PrefsUtils.getPort()
  @Bindable Boolean serverTfValid = true
  @Bindable Boolean portTfValid = true
}
</pre>
<p><em>Listing 9: the PrefsPanel Model class</em></p>
<p>The PrefsPanel’s view (Listing 10) is similarly simple.</p>
<pre>
panel(border: loweredBevelBorder(), constraints: CENTER) {
  tableLayout(cellpadding: 2) {
    tr {
      td { label("Server:") }
      td {
        textField(id: 'server', columns: 24,
          text: bind(source: model, 'server', mutual: true,
            validator: { controller.isNonBlank(server) }))
      }
    }
    tr {
      td { label("Port:") }
      td {
        textField(id: 'port', columns: 5,
          text: bind(source: model, 'port', mutual: true,
            validator: { controller.isInteger(port) }))
      }
    }
  }
}
</pre>
<p><em>Listing 10: an Excerpt from PrefsPanelView.groovy</em></p>
<p>Of interest here is the use of mutual binding. Mutual binding allows for view interactions to update the model (as is normal in a GUI application) and also allows the model to update the view component…a less frequently undertaken activity. Given that validation is also required, almost the complete model/view binding syntax is on display here.</p>
<p>The PrefsPanelController is mostly concerned with setting up and performing validation of the textfields. What is not related to validation is concerned with persisting the various preferences values and controlling the view’s destruction.</p>
<pre>
[…elided…]

class PrefsPanelController {
  // these will be injected by Griffon
  def model
  def view

  final gb = BorderFactory.createLineBorder(Color.GRAY)
  final rb = BorderFactory.createLineBorder(Color.RED)

  def isNonBlank = {tf -&gt;
    model.serverTfValid = (tf.text ==~ /\S+/)
  }
  def isInteger = {tf -&gt;
    try {
      def n = Integer.parseInt(tf.text)
      if ( ! (0..Short.MAX_VALUE - 1).contains(n))
        throw new IllegalArgumentException("Port out of range")
      model.portTfValid = true
      return n
    } catch (x) { /* NumberFormatExn, IllegalArgumentExn*/
      model.portTfValid = false
    }
  }
  private handleSaveButton = {-&gt;
    view.saveButton.enabled =
      model.portTfValid &amp;&amp; model.serverTfValid
  }
  void mvcGroupInit(Map args) {
    // this method is called after model and view are injected
    model.addPropertyChangeListener({evt -&gt;
      handleSaveButton()
    } as PropertyChangeListener)
    model.addPropertyChangeListener("portTfValid", {evt -&gt;
      view.port.border = model.portTfValid ? gb : rb
    } as PropertyChangeListener)
    model.addPropertyChangeListener("serverTfValid", {evt -&gt;
      view.server.border = model.serverTfValid ? gb : rb
    } as PropertyChangeListener)
  }
  def postInit() {
    view.server.text = model.server = PrefsUtils.getServer()
    view.port.text = model.port = PrefsUtils.getPort()
    model.serverTfValid =  isNonBlank(view.server)
    model.portTfValid = isInteger(view.port)
  }
  def closeWithoutSavingAction = {evt = null -&gt;
    view.preferencesFrame.visible = false;
    destroyMVCGroup('PrefsPanel')
  }
  def savePreferencesAction = {evt = null -&gt;
    PrefsUtils.setServer(model.server)
    PrefsUtils.setPort(model.port)
    closeWithoutSavingAction evt
  }
}
</pre>
<p><em>Listing 11: the PrefsPanelController class</em></p>
<h3>Validation</h3>
<p>Validation is one area where Griffon is still a rookie player. The basic framework is in place, but there are still a few ‘wrinkles’ that have yet to be worked out. The mvcGroupInit closure in Listing 11 shows how to react to changes in the model properties and how to update the view appropriately. Figure 5 shows the result of this.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_51.png" alt="figure_5" title="figure_5" width="352" height="232" class="alignnone size-full wp-image-949" /><br />
<em>Figure 5: Indicating an Error</em></p>
<p>The postInit closure defined in PrefsPanelController is required to work around a small problem where the initial values for a model are not validated before being bound to the view component(s). One has to ensure that the model <em>always</em> sees one change after binding so that validation can proceed [8].</p>
<p>This still provides a useful learning opportunity. The Gr3ClientController class contains this code:</p>
<pre>
def preferencesAction = {evt = null -&gt;
  def (m, v, c) = createMVCGroup('PrefsPanel')

  c.postInit()
}
</pre>
<p>This excerpt shows the use of Groovy’s multiple assignment facility to ease the processing of the list instance returned from the createMVCGroup method.</p>
<p>Griffon’s powerhouse lead developer Andres Almiray has discussed an alternative–and probably more general—approach to this issue on the griffon-user mail list:<a href="http://archive.codehaus.org/lists/org.codehaus.griffon.user/msg/001701ca7885$a4925f40$edb71dc0$@com.au">Binding and validating seems at odds&#8230;</a>.</p>
<h3>Persisting Preferences Data</h3>
<p>Since Griffon is capable of generating a standalone application, an applet and a Java WebStart application from the same codebase, preferences handling is not as straightforward as one might think initially: where to store a configuration file in the face of different operating system filesystem conventions and security schemes? Is the JNDI available? Is the Windows Registry an option? What API is most convenient? Something ostensibly so simple is actually quite a problem for portable code [9].</p>
<p>The java.util.prefs package provides a way for applications to store and retrieve user and system preference and configuration data. The data is stored persistently in an implementation-dependent backing store but is accessed in a consistent fashion regardless of type of code or underlying system.</p>
<p>The Gr3Client application wraps the Preferences API into a simple PreferenceUtils class, as shown in Listing 12.</p>
<pre>
import java.util.prefs.Preferences

class PrefsUtils {
  private static final SERVER_KEY = 'server'
  private static final DEFAULT_SERVER = 'localhost'
  private static final PORT_KEY = 'port'
  private static final DEFAULT_PORT = '8080'
  private static final prefs = Preferences.userRoot().node('/Gr3')
  static setServer = {s -&gt;
    prefs.put(SERVER_KEY, s)
    prefs.sync()
  }
  static getServer = {
    prefs.sync()
    prefs.get(SERVER_KEY, DEFAULT_SERVER)
  }
  static setPort = {p -&gt;
    prefs.put(PORT_KEY, p)
    prefs.sync()
  }
  static getPort = {
    prefs.sync()
    prefs.get(PORT_KEY, DEFAULT_PORT)
  }
}
</pre>
<p><em>Listing 12: the PreferencesUtils class</em></p>
<p>At first sight, this code seems to contain lots of unnecessary syncs (which flush changes and refreshes the local cached data from the underlying persistent store). Strictly speaking this is indeed so, but I found that the regime I have used here was very helpful when testing: I could manually ‘munge’ the preferences store [the windows registry in my case] and see those changes happen immediately. Frequent syncing actually represents quite a trivial overhead in the grand scheme of things, so I left them in.</p>
<h2><em>Using the REST Plugin</em></h2>
<p>REST support in Griffon is provided courtesy of a plugin written by Andres Almiray. Andres’ weblog (see “Learn More”) is a “must see” site for any Griffon developer. Andres has written an equivalent plugin for Grails which makes a visit to his weblog doubly rewarding.</p>
<p>Following normal Griffon practice, the REST plugin (version 0.2 at time of writing) is installed via:</p>
<pre>
griffon install-plugin rest
</pre>
<p>I have configured the REST plugin to only work its magic on services (“out of the box” it is configured to work on controllers). This line needs to be added/edited in conf/Application.groovy:</p>
<pre>
griffon.rest.injectInto = ["service"]
</pre>
<p>I have split the network-handling code into a separate service, created via the command line:</p>
<pre>
griffon create-service ServerService
</pre>
<p>ServerService is a very simple class. Listing 13 shows just one action closure from this class but the others are essentially identical.</p>
<pre>
def playAction = {value -&gt;
  withRest(id: 'play', uri: NetworkUtils.URI) {
    def resp = put(path: 'play',
            body: [amount: value],
            requestContentType: JSON,
            responseContentType: JSON)
    assert resp.status == 200
    resp.data.tote
  }
}
</pre>
<p><em>Listing 13: Excerpted ServerService Action</em></p>
<p>The REST-related code is exceptionally clear! If you walk through the invocation sequence, you will be able to see easily how the incoming request and associated response is processed.</p>
<p>Note how automatic JSON response parsing makes for clean code: there is no need for either side to marshal/unmarshal the value for tote to/ from the textual on-the-wire representation, for example.</p>
<p>One slight subtlety is concerned with the id given to the withRest method. To quote the REST plugin’s documentation:  <em>“All dynamic methods will create a new http client when invoked unless you define an id: attribute. When this attribute is supplied the client will be stored as a property on the instance&#8217;s metaClass. You will be able to access it via regular property access or using the id: again.”</em> This gives a nice ‘tuning’ ability in that it makes it possible to reduce the number of instances that are created and almost immediately destroyed. The ServerService makes use of this facility: playAction and winAction share an id (play), totalizerAction has an unique id (and thus an unique HTTPClient instance), while registerAction and unRegisterAction do not reuse connections (on the assumption that the time between register and unRegister operations could be very long and keeping an unused connection around would be counterproductive).</p>
<h3>Configuring Logging Support</h3>
<p>Even though the syntax enabled by the REST plugin is quite simple, as I developed the application I still needed to see the request-response interaction between the Gr3Client and Gr3Server. To do this, I turned to that tried and trusted standby: Log4J. Although Griffon uses Log4J internally, it does not actually make it available to an application at runtime.</p>
<p>Configuring run-time support for Log4J is not such a “no brainer” as it is for Grails, but is still a fairly simple 3-step process:</p>
<p>Step 1: Copy the log4j jar from the Griffon distribution’s lib directory into the application’s lib directory.<br />
Step 2: Create conf/Events.groovy with the contents shown in Listing 14.</p>
<pre>
import org.apache.log4j.Logger

onNewInstance = {klass, type, instance -&gt;
  instance.metaClass.logger =
    instance.metaClass.log =
      Logger.getLogger("gr3Client.${klass.name}")
}
</pre>
<p><em>Listing 14: Events.groovy Needed for Logging</em></p>
<p>This is quite a ‘shotgun’ approach: it injects a log property into everything. A more sophisticated variation of this code (“Left as an exercise for the reader”) would be better for ‘production’ use. For the current purposes, however, it is fine.</p>
<p>Step 3: Add the code shown in Listing 15 to lifecycle/Initialize.groovy. This is mostly an ‘inline’ Log4J configuration file.</p>
<pre>
import groovy.xml.DOMBuilder

def xml = """
&lt;log4j:configuration
  xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"&gt;
     &lt;appender
              &gt;
          &lt;param value="System.out" /&gt;
          &lt;layout&gt;
              &lt;param
                      value="%d{ISO8601} %-5p  %c{1} - %m%n" /&gt;
          &lt;/layout&gt;
     &lt;/appender&gt;
     &lt;category&gt;
          &lt;priority value="DEBUG" /&gt;
     &lt;/category&gt;
     &lt;!-- Use DEBUG to see basic request/response info;
          Use TRACE to see headers for HttpURLClient. --&gt;
     &lt;category&gt;
          &lt;priority value="TRACE" /&gt;
     &lt;/category&gt;
     &lt;category&gt;
          &lt;priority value="INFO" /&gt;
     &lt;/category&gt;
     &lt;category&gt;
          &lt;priority value="INFO" /&gt;
     &lt;/category&gt;
     &lt;category&gt;
          &lt;priority value="TRACE" /&gt;
     &lt;/category&gt;
     &lt;root&gt;
          &lt;priority value="DEBUG" /&gt;
          &lt;appender-ref ref="console" /&gt;
     &lt;/root&gt;
&lt;/log4j:configuration&gt;
"""

def reader = new StringReader(xml)
def doc = DOMBuilder.parse(reader)
new org.apache.log4j.xml.DOMConfigurator().
  configure(doc.documentElement)
</pre>
<p><em>Listing 15: Inline Log4J Configuration</em></p>
<p>The above three steps will turn on some quite extensive (and very useful!) debugging output from the REST plugin, as this excerpt (Listing 16, showing a single ‘play’ interaction) illustrates:</p>
<pre>
DEBUG RESTClient - PUT http://localhost:8080/Gr3Server/totalizer/play
DEBUG wire - &gt;&gt; "PUT /Gr3Server/totalizer/play HTTP/1.1[EOL]"
DEBUG wire - &gt;&gt; "Accept: */*[EOL]"
DEBUG wire - &gt;&gt; "Content-Length: 13[EOL]"
DEBUG wire - &gt;&gt; "Content-Type: application/json[EOL]"
DEBUG wire - &gt;&gt; "Host: localhost:8080[EOL]"
DEBUG wire - &gt;&gt; "Connection: Keep-Alive[EOL]"
DEBUG wire - &gt;&gt; "User-Agent: Apache-HttpClient/4.0 (java 1.5)[EOL]"
DEBUG wire - &gt;&gt; "Expect: 100-Continue[EOL]"
DEBUG wire - &gt;&gt; "Accept-Encoding: gzip,deflate[EOL]"
DEBUG wire - &gt;&gt; "[EOL]"
DEBUG wire - &lt;&lt; "HTTP/1.1 100 Continue[EOL]"
DEBUG wire - &lt;&lt; "[EOL]"
DEBUG wire - &gt;&gt; "{"amount":20}"
DEBUG wire - &lt;&lt; "HTTP/1.1 200 OK[EOL]"
DEBUG wire - &lt;&lt; "Server: Apache-Coyote/1.1[EOL]"
DEBUG wire - &lt;&lt; "Content-Type: application/json;charset=UTF-8[EOL]"
DEBUG wire - &lt;&lt; "Transfer-Encoding: chunked[EOL]"
DEBUG wire - &lt;&lt; "Date: Sat, 12 Dec 2009 11:34:05 GMT[EOL]"
DEBUG wire - &lt;&lt; "[EOL]"
DEBUG RESTClient - Response code: 200; found handler:
  org.codehaus.groovy.runtime.MethodClosure@a4911d
DEBUG RESTClient - Parsing response as: application/json
DEBUG wire - &lt;&lt; "b[EOL]"
DEBUG wire - &lt;&lt; "{"tote":40}"
DEBUG wire - &lt;&lt; "[\r]"
DEBUG wire - &lt;&lt; "[\n]"
DEBUG wire - &lt;&lt; "0[EOL]"
DEBUG wire - &lt;&lt; "[EOL]"
DEBUG RESTClient-Parsed data to instance of: class
  net.sf.json.JSONObject
</pre>
<p><em>Listing 16: Debugging a REST Interaction</em></p>
<p>This configuration can be easily ‘tweaked’ for any purpose, of course.</p>
<p>Don’t Panic! Recall that it is <em>still</em> quite “early days” for Griffon, and I believe that there has been some discussion aimed at eventually developing a logging plugin or addon. Forthcoming Spring framework support and the new ArtefactManager will also make the sort of configuration currently being performed in onNewInstance easier and more targeted in the future.</p>
<h2><em>A Little Gloss: SwingX Painters</em></h2>
<p>For those not already familiar with the SwingX project, here is the overview blurb from the SwingX home page:</p>
<p><em>“Contains extensions to the Swing GUI toolkit, including new and enhanced components that provide functionality commonly required by rich client applications. Highlights include: </em></p>
<ul>
<li><em>Sorting, filtering, highlighting for tables, trees, and lists</em></li>
<li><em>Find/search</em></li>
<li><em>Auto-completion</em></li>
<li><em>Login/authentication framework</em></li>
<li><em>TreeTable component</em></li>
<li><em>Collapsible panel component</em></li>
<li><em>Date picker component</em></li>
<li><em>Tip-of-the-Day component</em></li>
</ul>
<p><em>Many of these features will eventually be incorporated into the Swing toolkit.”</em></p>
<p>Griffon’s SwingX plugin packages all this goodness up and makes it easy to use alongside the normal Swing components. Don’t head down to the gaming tables without these components safely packed into your kitbag.</p>
<p>The SwingX JXHeader component supports a relatively new facility called painters. Listing 7 shows how a simple PinStripePainter can be defined and passed to the jxHeader stanza in the view builder and Figure 1 shows the results of this. Not too shabby, but not particularly breathtaking, either.</p>
<p>Listing 17 shows a more ‘beautiful’ alternative using a CompoundPainter.</p>
<pre>
def gloss = new GlossPainter(
        paint: new Color(1.0f, 1.0f, 1.0f, 0.2f),
        position: GlossPainter.GlossPosition.TOP)
def stripes = new PinstripePainter(
        paint: new Color(1.0f, 1.0f, 1.0f, 0.17f),
        spacing: 5.0)
def matte = new MattePainter(fillPaint: new Color(51, 51, 51))
def cp = new CompoundPainter(matte, stripes, gloss)
[…elided…]
jxheader(title: "Gr3",
      […elided…]
      backgroundPainter: cp)
</pre>
<p><em>Listing 17: a Compound Painter</em></p>
<p>As Figure 6 shows, this is much nicer and has a distinctly more ‘modern’ feel to it.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/05/figure_6.png" alt="figure_6" title="figure_6" width="330" height="242" class="alignnone size-full wp-image-950" /><br />
<em>Figure 6: the Compound Painter “In Action”</em></p>
<h2><em>Win Evaluation</em></h2>
<p>To perform win evaluation, the Gr3ClientController’s playAction closure calls the injected serverService. This is shown in Listing 18.</p>
<pre>
def playAction = {evt = null -&gt;
  doOutside {
    def lr = view.leftReel
    def mr = view.middleReel
    def rr = view.rightReel
    lr.activate()
    mr.activate()
    rr.activate()
    edt {
      view.spindle.repaint()
    }
    model.plays++
    def playedAmount =
      Integer.valueOf(view.playValue.selection.actionCommand)
    def pTote = serverService.playAction(playedAmount)
    model.totalizerValue = nf.format(pTote)
    model.playedValue =
      nf.format(playedAmount + nf.parse(model.playedValue))
    def res = evaluator.evaluate(lr, mr, rr)
    switch (res) {
      case EvaluatorResult.SMALLWIN:
      case EvaluatorResult.BIGWIN:
        model.playButtonEnabled = false
        def winnings =
          winningsService.evaluate(res.multiplier, playedAmount)
        model.earnings =
          nf.format(winnings + nf.parse(model.earnings))
        def wTote = serverService.winAction(playedAmount, winnings)
        model.totalizerValue = nf.format(wTote)
        switch (res) {
          case EvaluatorResult.SMALLWIN:
            model.message = "Congratulations! You just won: ${nf.format(winnings)}."
            SoundUtils.smallWin()
            break
          case EvaluatorResult.BIGWIN:
            model.message = "Hey BIG WINNER! You just won: ${nf.format(winnings)}."
            SoundUtils.bigWin()
            break
        }
        model.playButtonEnabled = true
        break
      default:
        model.message = CondolencesUtils.condolences()
        break
    }
  }
}
</pre>
<p><em>Listing 18: Win Evaluation</em></p>
<p>Within playAction threading issues are noteworthy, in particular the use of doOutside and edt to ensure correct and responsive view behavior.</p>
<p>Separating the evaluation into a separate service is beneficial and gives flexibility. It allows for the definition of a very simple ruleset like “A win occurs if each icon under the line is the same” or for more sophisticated rules taking into account such things as diagonal or alternate arrangements and the actual icons involved.</p>
<p>Listing 19 shows one possible (very simple) evaluator.</p>
<pre>
// simple function: a win is when all icons in the
//   middle position are the same
def evaluate = {lr, mr, rr -&gt;
  // assume that all reels have the same number of icons
  def mrm = mr.model
  int mid = mrm.size() / 2
  def le = lr.model.getElementAt(mid)
  def me = mrm.getElementAt(mid)
  def re = rr.model.getElementAt(mid)
  (le == me) &amp;&amp; (me == re) ?
    EvaluatorResult.SMALLWIN : EvaluatorResult.LOSE
}
</pre>
<p><em>Listing 19: A Very Simple Win Evaluator</em></p>
<p>It is possible to easily replace this simple code with a more sophisticated evaluator with very little knock-on effect [10].</p>
<h2><em>A Little Whimsy: JFugue</em></h2>
<p>No pokie can possibly be considered playable if it doesn’t have the capability to produce at least a few ear-splitting bells and whistles! In this case, incipient deafness comes courtesy of the excellent JFugue. In its own words:<em> “JFugue is an open-source Java API for programming music without the complexities of MIDI.”</em></p>
<p>Listing 20 shows how simple adding sound to your application can be.</p>
<pre>
import org.jfugue.Pattern
import org.jfugue.Player
class SoundUtils {
  private static final player = new Player()
  private static final smallPattern =
    new Pattern("T[Presto] I[Rock_Organ] Db4minH C5majH C5majW")
  private static final bigPattern =
    new Pattern(
      "T[Presto] I[Rock_Organ] Db4minH C5majH C5majW C5majH Db4minH")
  static smallWin = {-&gt; player.play(smallPattern) }
  static bigWin = {-&gt; player.play(bigPattern) }
}
</pre>
<p><em>Listing 20: the SoundUtils class</em></p>
<p>If you look back to Listing 18, you will see how this code is used within the playAction closure.</p>
<h1>Wrapping Up</h1>
<p>I hope that I have been able to show you that it’s not a gamble to use these technologies together. Both are powerful frameworks fully capable of permitting sophisticated development. The REST support in both makes writing distributed applications simple while the ability to incorporate existing code such as Log4J and JFugue simply cannot be beat.</p>
<p>I leave you with this quote from one of the ‘greats’ of Science Fiction, writer and social commentator Robert Heinlein: <em>“There is no such thing as ‘social gambling.’ Either you are there to cut the other bloke&#8217;s heart out and eat it—or you&#8217;re a sucker. If you don&#8217;t like this choice—don&#8217;t gamble.”</em></p>
<h1>Learn More</h1>
<ul>
<li>Grails home page, <a href="http://groovy.codehaus.org/">http://groovy.codehaus.org</a></li>
<li>Griffon home page, <a href="http://griffon.codehaus.org/">http://griffon.codehaus.org</a></li>
<li>Andres Almiray’s Weblog, <a href="http://www.jroller.com/aalmiray/">http://www.jroller.com/aalmiray/</a></li>
<li>Griffon REST Plugin page, <a href="http://griffon.codehaus.org/Rest+Plugin">http://griffon.codehaus.org/Rest+Plugin</a></li>
<li>Painter Tutorial, <a href="http://swinglabs.org/docs/frameworks/painters/index.jsp">http://swinglabs.org/docs/frameworks/painters/index.jsp</a></li>
<li>JFugue, the Java API for Music Programming, <a href="http://jfugue.org/">http://jfugue.org/</a></li>
<li>Josh Reed’s ButtonGroup shortcut, <a href="http://josh-in-antarctica.blogspot.com/2009/10/griffon-tip-silly-swingbuilder-tricks.html">http://josh-in-antarctica.blogspot.com/2009/10/griffon-tip-silly-swingbuilder-tricks.html</a></li>
</ul>
<p><em>Bob Brown is the director and owner of Transentia Pty. Ltd.. Based in beautiful Brisbane, Australia, Bob is a specialist in Enterprise Java and has found his niche identifying and applying leading-edge technologies and techniques to customers’ problems.</em></p>
<p>[1] As a youngling, I lived in Macau (the “Las Vegas of the East”) for a few years. I clearly remember the astonishment I felt when I saw the Casinos totalizer boards in action for the first time. The amount displayed updates so rapidly that the last 2-3 whole-dollar figures of the value are simply a continually-changing blur. The amount shown is strictly monotonically increasing, which added to the sense of awe I experienced.<br />
[2] An idempotent operation is one that has no side-effects and so can be repeated without changing the state of the system in any way; it is a pure read operation.<br />
[3] CRUD = Create, Retrieve, Update, Delete.<br />
[4] I will not go into the ‘mechanics’ of how to drive either Grails or Griffon here. The website for each technology (see “Learn More” for the URLs) covers those aspects very nicely.<br />
[5] Don’t Repeat Yourself; a key tenet of any developer worth their stake at the table.<br />
[6] According to Groovy’s documentation:<em> “AST Transformations provides Groovy with improved compile-time metaprogramming capabilities allowing powerful flexibility at the language level, without a runtime performance penalty.”</em> They give us compile-time code generation for boilerplate patterns, in other words.<br />
[7] SwingX support is provided by the swingx-builder plugin<br />
[8] Groovy Jira GROOVY-3939 tracks this issue, for the curious.<br />
[9] And all Java developers should aspire to write good portable code!<br />
[10] Indeed, I have a version that uses JBoss Drools but that’s probably a story for another time&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/05/10/another-groovymag-masterpiece-gambling-on-griffon-and-grails-going-gangbusters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing With GPars</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/03/05/playing-with-gpars/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/03/05/playing-with-gpars/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 23:17:40 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[GPars]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=834</guid>
		<description><![CDATA[Way, way, waaaay back, I became something of a minor Occam &#8216;guru&#8217; (I actually implemented a fair proportion of a compiler/runtime for Occam 1) and I have maintained an (academic and practical) interest in the field throughout my career (which is what I laughingly call what I do these days, see Will Code For Food [...]]]></description>
			<content:encoded><![CDATA[<p>Way, way, waaaay back, I became something of a minor Occam &#8216;guru&#8217; (I actually implemented a fair proportion of a compiler/runtime for Occam 1) and I have maintained an (academic and practical) interest in the field throughout my career (which is what I laughingly call what I do these days, see <a href="http://wordpress.transentia.com.au/wordpress/2009/02/05/will-code-for-food/">Will Code For Food</a> for more ;-))</p>
<p>It&#8217;s therefore natural for me to take a look at <a href="http://gpars.codehaus.org">GPars</a>.</p>
<p>In its own words, GPars is:</p>
<blockquote><p>an open-source concurrency library for Groovy that aims to give you multiple high-level abstractions for writing concurrent code in Groovy &#8211; map/reduce, fork/join, asynchronous closures, actors, agents, dataflow concurrency and other concepts, which aim to make your Groovy code concurrent with little effort.</p></blockquote>
<p>Ever played the charmingly-named <a href="http://en.wikipedia.org/wiki/Chinese_whispers">Chinese Whispers game</a> at a party? That&#8217;s what I&#8217;m going to play with here.</p>
<p>It&#8217;s a very simple example of a pipelined processing task. This sort of thing is very common in signal processing, process control and image munging.</p>
<p>In the applications I build here, there will be a source thread generating messages which are each then sent through a chain of intermediate threads to a sink thread, which simply bounces the message back down the chain. On each &#8217;sinkward&#8217; step the intermediaries may or may not munge the message in some way as it whispers it to the next step, so that the version that eventually makes its way back to the source may be changed in some unpredicatable way.</p>
<p>Here&#8217;s the image to keep in your head:</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/03/pipe.png" alt="pipe" title="pipe" width="672" height="225" class="alignnone size-full wp-image-849" /></p>
<p>GPars provides several alternative ways of tackling this problem.</p>
<p>Scala made the idea of <a href="http://programming-scala.labs.oreilly.com/ch09.html">Actors</a> popular, so that&#8217;s a good starting point. </p>
<p>This is what the GPars doco says about Actors:</p>
<blockquote><p>The actor support in gpars were inspired by the Actors library in Scala but have meanwhile gone beyond that.</p>
<p>Actors allow for a messaging-based concurrency model, built from independent active objects that exchange messages and have no mutable shared state.</p></blockquote>
<p>If you are a webby-person, you can think of an Actor as a Servlet&#8230;you won&#8217;t go far wrong.</p>
<p>Coming up is a version of &#8220;Chinese Whispers&#8221; implemented using GPars&#8217; Actors:</p>
<pre>package chinesewhispers

@GrabResolver(name = 'jboss', root = 'http://repository.jboss.org/maven2/')
@Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.9')

import groovyx.gpars.actor.*
import chinesewhispers.utils.Whisperer

Actors.defaultPooledActorGroup.resize 16

class Stop {}
class Go {}

final intermediaries = []

def src = Actors.actor {index -&gt;
  println "Source; Starting..."
  react { Go go -&gt;
    println "Source; time to 'Go'"
    def msg = 'The sky is green, the trees are blue...SNAFU!'
    println "Source; message is: $msg"
    for (i in 0..&lt;8) {
      intermediaries[1].sendAndContinue msg, { ix, reply -&gt;
        println "Source[$ix]; received: '$reply'"
      }.curry(i)
    }
    intermediaries[1].send(new Stop())
    stop()
    print "Source; ...Stopped."
  }
}

intermediaries &lt;&lt; src

for (i in 1..8) {
  intermediaries &lt;&lt; Actors.messageHandler({ index -&gt;
    when {Stop msg -&gt; intermediaries[index + 1].send msg; stop(); }
    when {msg -&gt;
      def sender = msg.sender
      intermediaries[index + 1].sendAndContinue Whisperer.whisper("${msg}"), { reply -&gt;
        sender.send reply
      }
    }
  }.curry(i))
}

intermediaries &lt;&lt; Actors.messageHandler {
  when { Stop msg -&gt; stop() }
  when { msg -&gt; reply msg }
}

src &lt; &lt; new Go()

intermediaries*.join()</pre>
<p>This simple script creates a list of Actors, with a source Actor first, followed by a number of essentially identical intermediary Actors and finally a sink Actor.</p>
<p>Here it all is, &#8220;in action&#8221; (pun intended):</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/03/ChineseWhisperingActors.png" alt="ChineseWhisperingActors" title="ChineseWhisperingActors" width="603" height="292" class="alignnone size-full wp-image-856" /><br />
GPars creates Actors in a runnable state so that it is easy to start things off by sending the Source a unique Go message.</p>
<p>Notice how each Actor sends a message and then allocates a closure to asynchrounously handle the appropriate return message. This ensures that intermediaries get new work as soon as possible, so the pipeline is always running at full capacity. This makes for a very performant solution.</p>
<p>It&#8217;s a truism that getting a parallel system off and running is fairly easy, but getting one to Stop properly can be surprisingly tricky. For this application, the Source Actor&#8217;s last activity before it finishes is to send a (guaranteed-to-be-unique, obviously) Stop message up the pipline. On receipt of a Stop, each intermediate Actor simply forwards the message and then terminates in a nice orderly fashion. the final Sink Actor receives the forwarded Stop and simply stops without trying to send the message back down the chain of intermediaries (since the chain is effectively no longer there).</p>
<p>The messageHandler closure&#8217;s distinct &#8216;when&#8217; syntax makes the sort of message dependent processing shown here very easy.</p>
<p>The final line of the script simply waits for all Actors to finish shutting down before allowing the overall script to exit.</p>
<p>Simple, performant and easy to write and comprehend. What&#8217;s not to like!</p>
<p>GPars actors are not perfect (they lack some of the Scala library&#8217;s more subtle abilities such as pattern matching to guard message reception, and the ability to see the length of the incoming mesage queue), but they&#8217;re not too shabby, either.</p>
<p>For a second bite at the apple, here&#8217;s the DataFlow version.</p>
<p>According the the doco:</p>
<blockquote><p>Dataflow concurrency offers an alternative concurrency model, which is inherently safe and robust. It puts emphasis on the data and their flow though your processes instead of the actual processes that manipulate the data. Dataflow algorithms relieve developers from dealing with live-locks, race-conditions and make dead-ocks[sic] deterministic and thus 100% reproducible. If you don&#8217;t get dead-locks in tests you won&#8217;t get them in production.</p></blockquote>
<p>What does a Dataflow-based Chinese Whispers program look like? Viola:</p>
<pre>
package chinesewhispers

@GrabResolver(name = 'jboss', root = 'http://repository.jboss.org/maven2/')
@Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.9')

import groovyx.gpars.dataflow.*
import chinesewhispers.utils.Whisperer

class Link {
  final up = new DataFlowVariable()
  final down = new DataFlowVariable()

  Link(index) {
    /*
      up &gt;&gt; {println "The up[$index] variable has just been bound to $it"}
      down &gt;&gt; {println "The down[$index] variable has just been bound to $it"}
    */
  }
}

final NINT = 8

for (iteration in 0..&lt;8) {
  final intermediaries = []
  for (i in 0..&lt;NINT)
    intermediaries &lt;&lt; new Link(i)

  DataFlow.task {
    intermediaries[0].up &lt;&lt; 'The sky is green, the trees are blue...SNAFU!'
    println intermediaries[0].down.val
  }

  for (i in 1..&lt;NINT) {
    DataFlow.task({ index -&gt;
      intermediaries[index].up &lt;&lt; Whisperer.whisper(intermediaries[index - 1].up.val)
    }.curry(i))
    DataFlow.task({ index -&gt;
      intermediaries[index - 1].down &lt;&lt; intermediaries[index].down.val
    }.curry(i))
  }

  DataFlow.task {
    intermediaries[NINT - 1].down &lt;&lt; "Did you REALLY mean to say: '${intermediaries[NINT - 1].up.val}'?"
  }
}
"OK"
</pre>
<p>Neat, eh? Simple assignment to a variable, or reading a variable&#8217;s value performs inter-task communication. No messy send and receive mechanisms here!</p>
<p>Here&#8217;s what it looks like when running inside IntelliJ:</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/03/ChineseWhisperingDataflow.png" alt="ChineseWhisperingDataflow" title="ChineseWhisperingDataflow" width="655" height="199" class="alignnone size-full wp-image-848" /></p>
<p>Of course, you lose a fair bit of flexibility, but for straightforward tasks the simplicity of the solution more than compensates&#8230;</p>
<p>Each bi-directional link between intermediary tasks is modelled as a Link with a separate &#8216;up&#8217; and a &#8216;down&#8217; variable. Although GPars offers alternatives, for this application I have chosen to use plain &#8220;Dataflow Variables&#8221;, which are write-once, read-many entities; each iteration through the main loop thus recreates the requisite Link instances (and hence the Dataflow Variables) from scratch.</p>
<p>Uncomment the body of the Link constructor and you&#8217;ll be able to see the inter-task communication in action. Simple but very effective debugging:</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/03/ChineseWhisperingDataflowDebug.png" alt="ChineseWhisperingDataflowDebug" title="ChineseWhisperingDataflowDebug" width="999" height="238" class="alignnone size-full wp-image-854" /></p>
<p>Just for completeness sake (it&#8217;s a minor supporting actor, not a star): here&#8217;s the Whisperer class that the examples use:</p>
<pre>package chinesewhispers.utils

class Whisperer {
  final static r = new Random()

  final static map = [
          'sky': 'elephant',
          'trees': 'kettles',
          'green': 'effervescent',
          'blue': 'smelly'
  ]

  static whisper(msg) {

    if (r.nextBoolean())
      return msg

    def split = msg.split(/\W/).findAll { it }
    def l = split.size()
    def sel = r.nextInt(l)
    def word = split[sel]

    def w = map[word]
    w ? msg.replace(word, w) : msg
  }
}
</pre>
<p><a href="http://en.wikipedia.org/wiki/Porky_Pig">That&#8217;s all folks</a>; two versions of the same application is enough for any mortal!</p>
<p>I am eagerly looking forward to the time when the work to integrate <a href="http://www.cs.kent.ac.uk/projects/ofa/jcsp/">JCSP</a> into GPars bears fruit.</p>
<p>By the way, each of these examples should happily work with GPars 0.9 and Groovy 1.7.1. Just copy the listings into GroovyConsole and go (you might need to bring the Whispers class inline into each application, but that&#8217;s trivial to do).</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/03/05/playing-with-gpars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Old (Groovy) Switch-eroo Again&#8230;</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/23/the-old-groovy-switch-eroo-again/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/23/the-old-groovy-switch-eroo-again/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 11:29:17 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=796</guid>
		<description><![CDATA[Recently, I had the little task of looking at a string and deciding what to do based on the various values of an embedded prefix field.
I had to ask around a bit (thanks Paul!) to get the solution to my liking, but here&#8217;s yet another example of my favourite Groovy construct, the switch statement:

def days [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I had the little task of looking at a string and deciding what to do based on the various values of an embedded prefix field.</p>
<p>I had to ask around a bit (thanks Paul!) to get the solution to my liking, but here&#8217;s yet another example of my favourite Groovy construct, the switch statement:</p>
<pre>
def days = [
  "Monday:I could wait till Tuesday",
  "Tuesday:must make up my mind",
  "Wednesday:would be fine",
  "Thursday:she's on my mind",
  "Friday:give me time",
  "Saturday:I could wait",
  "Sunday:would be too late"
]

final MON = 'Monday:'
final TUE = 'Tuesday:'
final WED = 'Wednesday:'
final THU = 'Thursday:'
final FRI = 'Friday:'
final SAT = 'Saturday:'
final SUN = 'Sunday:'

days.each { value ->
  switch(value) {
    case ~/^${MON}.*$/:
      println "$MON: ${value - MON}"
      break
    case ~/^${TUE}.*$/:
      println "$TUE: ${value - TUE}"
      break
    case ~/^${WED}.*$/:
      println "$WED: ${value - WED}"
      break
    case ~/^${THU}.*$/:
      println "$THU: ${value - THU}"
      break
    case ~/^${FRI}.*$/:
      println "$FRI: ${value - FRI}"
      break
    case ~/^${SAT}.*$/:
      println "$SAT: ${value - SAT}"
      break
    case ~/^${SUN}.*$/:
      println "$SUN: ${value - SUN}"
      break
  }
}
</pre>
<p>I know it&#8217;s a <em>very </em>contrived example, but take a look at the case &#8216;labels&#8217;: regular expressions that reference properties found elsewhere in the code. Neat-o!</p>
<p>Apologies to Sting (did you get <a href="http://www.lyricsfreak.com/s/sting/seven+days_20132076.html">the song</a>?)!</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/23/the-old-groovy-switch-eroo-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GroovyMag February 2010: Another Article By Yours Truly</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/10/groovymag-february-2010-another-article-by-yours-truly/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/10/groovymag-february-2010-another-article-by-yours-truly/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 22:58:40 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Griffon]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=776</guid>
		<description><![CDATA[Another GroovyMag USD$4.99 blockbuster.
This time taking a look at the combination of Grails, Griffon and a REST-like interaction style. It&#8217;s all Good Stuff.

Worth every cent.
]]></description>
			<content:encoded><![CDATA[<p>Another <a href="http://groovymag.com">GroovyMag</a> USD$4.99 blockbuster.</p>
<p>This time taking a look at the combination of <a href="http://www.grails.org">Grails</a>, <a href="http://griffon.codehaus.org/">Griffon</a> and a <a href="http://www.infoq.com/articles/rest-introduction">REST</a>-like interaction style. It&#8217;s all Good Stuff.</p>
<p><a href="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/02/gm16_400.jpg"><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/02/gm16_400-231x300.jpg" alt="gm16_400" title="gm16_400" width="231" height="300" class="alignnone size-medium wp-image-777" /></a></p>
<p>Worth <em>every cent</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/10/groovymag-february-2010-another-article-by-yours-truly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Copy Image From URL To File</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/08/copy-image-from-url-to-file/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/08/copy-image-from-url-to-file/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 09:22:21 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=763</guid>
		<description><![CDATA[Just saving this away for a rainy day&#8230;something I concocted in response to a question on the Groovy mailing list:

new File("local.gif").withOutputStream { os ->
  new URL("remote.gif").withInputStream { is ->
    os &#60;&#60; is
  }
}

The important thing to note here is the way the streams are carefully &#8217;scoped&#8217; and maintained so that [...]]]></description>
			<content:encoded><![CDATA[<p>Just saving this away for a rainy day&#8230;something I concocted in response to <a href="http://groovy.markmail.org/message/yyzshsnzes5vgs75">a question</a> on the Groovy mailing list:</p>
<pre>
new File("local.gif").withOutputStream { os ->
  new URL("remote.gif").withInputStream { is ->
    os &lt;&lt; is
  }
}
</pre>
<p>The important thing to note here is the way the streams are carefully &#8217;scoped&#8217; and maintained so that no leaks can occur even if exceptions or other sticky situations arise.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/08/copy-image-from-url-to-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Groovy Internet Mood Meter in SVG</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/04/the-groovy-internet-mood-meter-in-svg/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/04/the-groovy-internet-mood-meter-in-svg/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 10:24:36 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=728</guid>
		<description><![CDATA[This is yet another GroovyMag article.
This one was published in September 2009 and is still running on Stax (just follow that last link to learn more).
Since the time of writing, Microsoft has announced that it&#8217;s joining the SVG working group (about bloody time!).


The Groovy Internet Mood Meter in SVG
Embedding and updating scalable vector graphics in [...]]]></description>
			<content:encoded><![CDATA[<p>This is yet another <a href="http://www.groovymag.com/">GroovyMag</a> article.</p>
<p><a href="http://wordpress.transentia.com.au/wordpress/2009/09/03/grimmis-in-groovymag/">This one was published in September 2009</a> and is still running on Stax (just follow that last link to learn more).</p>
<p>Since the time of writing, Microsoft has <a href="http://blogs.msdn.com/ie/archive/2010/01/05/microsoft-joins-w3c-svg-working-group.aspx">announced</a> that it&#8217;s joining the SVG working group (<a href="/wordpress/2010/01/11/about-bloody-time/">about bloody time!</a>).</p>
<hr />
<a href="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/02/gm11_400.jpg"><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/02/gm11_400-231x300.jpg" alt="gm11_400" title="gm11_400" width="231" height="300" class="alignnone size-medium wp-image-753" /></a><br />
<strong>The Groovy Internet Mood Meter in SVG<br />
Embedding and updating scalable vector graphics in XHTML</strong></p>
<p><em>XML is a very effective tool promoting data interchange between disparate systems. It&#8217;s a useful weapon that is slowly helping to quell the numerous &#8220;format wars&#8221; that have been fought throughout the history of IT. One of the ongoing but lesser known skirmishes concerns graphics. The plethora of current formats is confusing, costly, and simply not appropriate for the needs of advanced web applications. With most current formats, intricate drawings are far too large, difficult to produce and hard to use. Anyone who has battled with HTML image maps knows that the traditional image formats provide almost no opportunity for sophisticated scripting and interactivity. Scalable Vector Graphics (SVG) is an application of XML that solves all of the previously mentioned problems and also provides an open, standards-based alternative to the common graphics formats in use today. GrIMMiS is a very small Grails application I have cooked up that lets me use AJAX to dynamically update portions of an SVG drawing–and bring a peaceful end to the format wars.</em></p>
<h1>A brief overview</h1>
<p>This little dish has a bunch of tasty ingredients!  There&#8217;s Grails, JavaScript (plain and using Grails&#8217; support for prototype/AJAX), SVG (with a small amount of declarative animation), and XHTML, all rolled into one neat little savory package.</p>
<p>The Groovy Internet Mood Meter in SVG (GrIMMiS) itself is intentionally pretty simple: when you click on the smiley that best reflects your mood you influence the meter value, which is updated appropriately. The meter also periodically updates to reflect the ongoing cumulative mood of &#8220;the Internet.&#8221; With each update, GrIMMiS also retrieves a pithy saying or joke that varies depending on the overall mood.</p>
<p>Figure 1 shows GrIMMiS in all its glory running in Opera 10 beta 2, which currently (to me) seems to offer the best SVG support.</p>
<p>[images/image_1.png]</p>
<p>Figure 1: The GrIMMiS application</p>
<p>GrIMMiS mirrors the basics of a real SCADA HMI (Supervisory Control and Data Acquisition Human-Machine Interface) application that I developed for a client a long time ago–even before Jesse James Garrett&#8217;s coined the term ‘AJAX&#8217; in the shower[1]. My original application was written in Java with plain JavaScript and had a fair amount of messy XML processing. In writing GrIMMiS, I wanted to see how Groovy and Grails would improve things. Of course, I found that the two technologies made things a lot simpler.</p>
<h2>The SVG image</h2>
<p>In preparation for the upcoming HTML5 standard, most modern browsers are supporting SVG more and more faithfully with each release. SVG is now available as a standard feature in Opera, Firefox, Safari and Chrome. It is found everywhere from JEE applications to mobile phone displays and frequently crops up in unexpected places. For example, much of the KDE4 Desktop&#8217;s user interface has been styled with SVG, and SVG can also be used to render UML diagrams in Oracle&#8217;s JDeveloper IDE.</p>
<p>Notably absent is Microsoft&#8217;s Internet Explorer [2]. In My (not-so) Humble Opinion, Redmond should be thoroughly ashamed of itself; SVG support is by far the most requested new feature for IE yet the community&#8217;s pleas have continually fallen on deaf ears. Adobe also should be ashamed of their &#8220;bait and switch&#8221; behavior in supplying the ‘anointed&#8217; SVG plugin for IE and then unceremoniously pulling the plug, leaving the community high and dry with no alternative but to move to proprietary systems like flash/flex, and indirectly opening the door for Silverlight. Even worse, Adobe still supports SVG in applications like Adobe Reader and many other products but will no longer provide that support for IE. All is not lost however: there is evidence that Google is tiring of waiting for Microsoft to support SVG on IE and has launched its own SVG project called &#8220;SVG Web&#8221; [3]. Examotion is also developing the RENESIS plugin, which is intended to be a re-engineering of the Adobe plugin [4].</p>
<p>Enough background chit-chat! Listing 1 shows the source for the meter portion of the image that is shown in Figure 1.</p>
<pre>&lt;svg xmlns="http://www.w3.org/2000/svg"
     version="1.1"
     width='600'
     height='250'&gt;
&lt;style type="text/css"&gt;
  text {
    font-size:12px;
    text-anchor:middle;
    font-family:sans-serif;
  }
  .bold {
  font-weight:bold;
  }
&lt;/style&gt;
&lt;g id='meterGroup'&gt;
  &lt;circle cx="400" cy="25" r="10"
          fill="white" stroke="black" stroke-width="1"&gt;
    &lt;animateColor attributeName="fill"
                  attributeType="CSS" values="white;white;blue;white"
                  keyTimes="0;0.70;0.75;1.0"
                  repeatCount="indefinite"
                  dur="5s" /&gt;
  &lt;/circle&gt;

  &lt;path d="M 300,180 L 550,180 A 248 248 1 0 0 400,25"
        fill="crimson" stroke="black" stroke-width="1" /&gt;
  &lt;path d="M 300,180 L 400,25 A 220 220 1 0 0 200,25"
        fill="lightGray" stroke="black" stroke-width="1" /&gt;
  &lt;path d="M 300,180 L 200,25 A 248 248 1 0 0 50,180 L 300,180"
        fill="RoyalBlue" stroke="black" stroke-width="1" /&gt;
  &lt;g id='pointerGroup' transform="translate(300,180)"&gt;
    &lt;g id='pointerRotateTransform' transform="rotate(-90)"&gt;
      &lt;line x1='0' y1='0' x2='150' y2='0'
           fill="yellow" stroke="yellow"
           stroke-width="15" stroke-linecap="round" /&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;circle cx="300" cy="180" r="20" fill="black" stroke="darkGray"
  stroke-width="3px" /&gt;
  &lt;text x="300" y="220" id="reading" class="bold"&gt;90.0&lt;/text&gt;
  &lt;text x="300" y="240" id="joke"&gt;&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;</pre>
<p>Listing 1: The SVG Meter Image source code</p>
<p>There are a number of points of interest in this code (it sounds a little weird talking about the source-code for an image, doesn&#8217;t it, but that&#8217;s what we have here).</p>
<p>First, SVG is an application of XML and therein lies one of its great strengths: there are many XML tools and techniques available for processing XML, and used with SVG as well, making it easy to create and process images programmatically.</p>
<p>Secondly, the ability to use Cascading Style Sheets (CSS) is another great strength. Given that SVG is a first-class member of the large set of web technologies promulgated by the World Wide Web Consortium (W3C), one would expect nothing less than that CSS and (as we will see) JavaScript work without hassle.</p>
<p>Various elements of the drawing are self explanatory: circle, line, text . Note that several elements have been given unique values for their id attribute: this will simplify later processing.</p>
<p>The g element introduces a group. The important point of interest here is that the g element allows the specification of a transform attribute. Transforms can be used to rotate, translate, scale and skew any portion of an image. In this image, the line element within the ‘pointerGroup&#8217; g element is initially defined as if it were at position 0,0 and pointing straight to the right, and then translated and rotated into its proper place and orientation. Although this may seem strange at first, this facility allows complex images to be built up from independent sub-parts that are ‘munged&#8217; into place as needed. The power of all this becomes apparent when one realizes that the various sub-parts may have been produced in isolation, or perhaps generated as the result of a data query or other program action, without reference to any particular subsequent use. In this way, SVG is designed to make it easy to put together reusable ‘clip-art&#8217;-style libraries.</p>
<p>The three path elements draw the three wedges that make the dial of the meter. The key point of interest here is the mini &#8220;turtle graphics-style&#8221; language embedded into the d (path data) attribute. For example, the first line element decodes as:</p>
<pre>M   absolute moveto         x, y

L   absolute lineto             x, y

A   absolute arc               rx ry x-axis-rotation short-or-long-way-flag clock-anticlock-flag x, y</pre>
<p>The first circle makes use of the declarative animation provided by SVG. This is actually another W3C-originated technology called Synchronized Multimedia Integration Language (SMIL; pronounced &#8220;smile&#8221;). The animation rule declared here periodically manipulates the circle&#8217;s CSS fill property to provide a ‘busy&#8217; indicator: every 5 seconds the circle will flash blue for 1.2 seconds. Not every browser currently handles SVG declarative animation; for instance, most fairly recent versions of Opera do but Firefox 3.5.1 does not.</p>
<p>The final point to note is the rule that defines z-order layering of the image elements: textually later elements appear on top of earlier ones.</p>
<p>If all this XML still leaves you unconvinced, consider this: the SVG document is less than 1.5Kb in size, while the equivalent PNG image is about 16Kb; more complex diagrams save even more. When you consider that Yahoo [5] estimated that roughly 80% of its web traffic involves image downloads, savings of one or two orders of magnitude start to look really attractive.</p>
<h2>The XHTML ‘Container&#8217; GSP page</h2>
<p>In GrIMMiS, the SVG image source shown in Listing 1 is itself embedded into an XHTML document.  This is the first true ingredient of the GrIMMiS Grails application because the XHTML is produced via a Groovy Server Pages (GSP) page, shown as Listing 2.</p>
<pre>&lt; %@ page contentType="application/xhtml+xml" %&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="en" lang="en"&gt;
&lt;head&gt;
  &lt;title&gt;GrIMMiS&lt;/title&gt;

  &lt;link rel="stylesheet" type="text/css" href="&lt;g:resource dir='css' file='grimmis.css' /&gt;" /&gt;

  &lt;g:javascript library="prototype"/&gt;

  &lt;script type="text/javascript"&gt;
    //&lt;![CDATA[
    var POLL_TIME = 5;
    var PRTEL = 'pointerRotateTransform';
    var JEL = 'joke';
    var REL = 'reading';

    function init() {
      new PeriodicalExecuter(function(pe) {
        new Ajax.Request('&lt;g:createLink controller="grIMMiS" action="poll" /&gt;', {
          method: 'get',
          onSuccess: onSuccessFunction
        });
      }, POLL_TIME);
    }

    function onSuccessFunction(e) {
      var XML = e.responseXML
      var rel = XML.getElementById(REL);
      var n = $('meter').suspendRedraw(500);
      var reading = $(REL);
      reading.parentNode.replaceChild(rel, reading);
      var prtel = XML.getElementById(PRTEL);
      var pointerRotateTransform = $(PRTEL);
      pointerRotateTransform.parentNode.replaceChild(prtel, pointerRotateTransform);
      var jel = XML.getElementById(JEL);
      var joke = $(JEL);
      joke.parentNode.replaceChild(jel, joke);
      $('meter').unsuspendRedraw(n);
    }
    //]]&gt;
  &lt;/script&gt;
&lt;/head&gt;
&lt;body onload="init();"&gt;
&lt;h1&gt;GrIMMiS—the Groovy Internet Mood Meter in SVG&lt;/h1&gt;

&lt;table class="layout centered"&gt;
  &lt;tr&gt;
    &lt;td colspan="3"&gt;How is the Internet feeling today?&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td colspan="3"&gt;
      &lt;svg xmlns="http://www.w3.org/2000/svg"
           version="1.1"
           class="svg"
           id='meter'&gt;
        &lt;g:include controller="grIMMiS" action="svg"&gt;&lt;/g:include&gt;
      &lt;/svg&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td colspan="3"&gt;How are &lt;em&gt;you&lt;/em&gt; feeling today?&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;g:remoteLink controller='grIMMiS' action='sad' onSuccess='onSuccessFunction(e);'&gt;
      &lt;img src="images/nicubunu_Smiley_Cry.png" class="button" title="Sadder"/&gt;
    &lt;/g:remoteLink&gt;
    &lt;/td&gt;
    &lt;td&gt;&lt;g:remoteLink controller='grIMMiS' action='neutral' onSuccess='onSuccessFunction(e);'&gt;
      &lt;img src="images/nicubunu_Smiley_Puzzled.png" class="button" title="Neutraller"/&gt;
    &lt;/g:remoteLink&gt;
    &lt;/td&gt;
    &lt;td&gt;&lt;g:remoteLink controller='grIMMiS' action='happy' onSuccess='onSuccessFunction(e);'&gt;
      &lt;img src="images/nicubunu_Smiley_Laugh.png" class="button" title="Happier"/&gt;
    &lt;/g:remoteLink&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;div class="footer"&gt;transentia pty. ltd.; 13/July/2009&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Listing 2: The Container XHTML GSP page</p>
<p>Listing 2 has a number of ingredients worth noting.</p>
<p>Since this is a GSP, I am able to use Grails taglibs like &lt;g:resource&gt;, &lt;g:createLink&gt; and &lt;g:remoteLink&gt; to reference resources (such as grimmis.css) in a nice neat way, and to cleanly use AJAX to talk back to the GrIMMiS controller&#8217;s various actions. This allows me to manipulate the remote meter values or to update the local SVG drawing.</p>
<p>Note that the page retrieves the actual SVG image via the GrIMMiS controller&#8217;s svg closure and includes it inline (by using &lt;g:include&gt;), rather than load it via a separate HTTP connection. This makes slightly more efficient use of the network, and having the image included inline in this fashion gives a unified Document Object Model (DOM). This greatly simplifies DOM processing and helps with cross-browser compatibility.</p>
<p>I have also made use of SVG&#8217;s ability to have nested SVG elements. This lets me build the actual image–without worrying how it might eventually be used in the page–while applying SVG-specific styling, and a unique ID to the outer SVG element.</p>
<p>I am using Grails&#8217; prototype library for AJAX support and since I need the meter to regularly update to show the prevailing &#8220;mood out there,&#8221; I am hand-crafting a small bit of JavaScript/prototype code: using Ajax.PeriodicalExecutor in conjunction with a Ajax.Request for regularly (every POLL_TIME seconds) polling back to the GrIMMiS controller&#8217;s poll closure.</p>
<p>Polling is initiated by the client&#8217;s browser as it executes the XHTML page&#8217;s onload handler.</p>
<p>The JavaScript callback function ‘onSuccessFunction&#8217; is the meat of this little recipe. It is called after every successful AJAX operation to process the retrieved data. As expected, The GrIMMiS controller sends a small XML document to the client in response to each AJAX request. onSuccessFunction takes this incoming document, extracts the relevant fragments from it (those that represent new values for the elements of the drawing that are to be updated), locates the now-superseded original fragments in the SVG document and replaces them. The meter is automatically redrawn after being updated.</p>
<p>Note how onSuccessFunction uses the suspendRedraw/unSuspendRedraw functions to turn document redraw on and off during updates; this can greatly improve browser performance.</p>
<p>onSuccessFunction is slightly trickier than I would really like: it is able to use prototype&#8217;s $(‘<em>element&#8217;</em>) syntax for addressing elements in the larger HTML document (and thus, the embedded SVG as well), but must use plain JavaScript to work with the elements of the XML fragment received from Grails. This is slightly painful, but bearable, and the various workarounds that exist (such as adding the received document&#8217;s elements into a hidden div and then shuffling them into place) may be worse than the cure in terms of readability.</p>
<p>The final point of interest on this page concerns the use of Grails&#8217; &lt;g:remoteLink&gt; tag to handle AJAX-style interaction with the controller when activated by the smiley-face image buttons that  increase/decrease/‘neutralize&#8217; the meter&#8217;s value.</p>
<h2>The Grails controller</h2>
<p>Listing 3 shows the single, very simple controller which is responsible for serving the SVG image and handling any interactions with the client browsers.</p>
<pre>class GrIMMiSController {

  def drawingService

  def index = { redirect(action: svg) }

  // get full document
  def svg = {
    render(text: drawingService.svg(), contentType: 'image/svg+xml', encoding: 'UTF-8')
  }

  // get changes for document
  def poll = {model = null -&gt;
    render(text: drawingService.poll(), contentType: 'text/xml', encoding: 'UTF-8')
  }

  def happy = {
    drawingService.happier()
  }

  def sad = {
    drawingService.sadder()
  }

  def neutral = {
    drawingService.neutraller()
  }

  // this interceptor means that happy, sad and neutral don't have to explicitly call poll()...DRY goodness
  //
  // must be elaborated after def poll = { } ... otherwise poll will be null
  def afterInterceptor = [action: poll, only: ['happy', 'sad', 'neutral']]
}</pre>
<p>Listing 3: The Grails controller</p>
<p>This controller is a thin adapter that mostly delegates to the injected drawingService instance.</p>
<p>The major point of interest here is the use of an afterInterceptor. Without this interceptor, each happy, sad and neutral smiley-face image buttons would need to look something like:</p>
<pre>def action = {

// body

poll()

}</pre>
<p>With this interceptor in place, these actions are much simpler and more DRY.</p>
<p>Note that the poll action can be invoked either as a result of an incoming HTTP request as an action in its own right or as the callback closure associated with the defined afterInterceptor. In the former case, no parameter is passed into the closure, while in the latter case a parameter is passed in by the actual interceptor code (although it isn&#8217;t used in this example). The use of a default parameter value helps avoid redundancy.</p>
<p>The single tricky point here is that afterInterceptor must be declared after poll has been fully declared, otherwise poll will be null at the point of declaration, and Grails will complain when one of the designated actions is invoked.</p>
<h2>The Grails service</h2>
<p>Most of the meat of the Grails application lives in the service class and a couple of small subsidiary classes.</p>
<p>Listing 4 shows the DrawingService.groovy file.</p>
<pre>import groovy.util.XmlNodePrinter

class DrawingService {

  boolean transactional = false

  static scope = "singleton"

  def jokeService

  final MIN = 0
  final MAX = 180
  final QMAX = MAX / 4
  final HMAX = MAX / 2
  final BOTTOM_QUAD = MIN..&lt;QMAX
  final LOW_QUAD = QMAX..&lt;HMAX
  final HIGH_QUAD = HMAX + 1..&lt;(HMAX + QMAX)
  final TOP_QUAD = (HMAX + QMAX)..MAX

  final mood = new Mood(range: MIN..MAX)

  def document

  def pointerRotateTransform
  def joke
  def reading

  def initialise = {file -&gt;
    def start = System.currentTimeMillis()
    log.debug "Initialise START: $file"
    log.debug "Parsing..."
    this.document = new XmlParser().parseText(new File(file).text)
    log.debug "Isolating important elements for updating..."
    this.pointerRotateTransform = document.g.g.g.find { it.'@id' == 'pointerRotateTransform' }
    log.debug "Found pointerRotateTransform: $pointerRotateTransform"
    this.joke = document.g.text.find { it.'@id' == 'joke' }
    log.debug "Found joke: $joke"
    this.reading = document.g.text.find { it.'@id' == 'reading' }
    log.debug "Found reading: $reading"
    log.debug "Initialise END; (${System.currentTimeMillis() - start}ms)"
  }

  // get full document
  def svg = {-&gt;
    synchronized (this) {
      toSVG document
    }
  }

  def poll = {-&gt;
    synchronized (this) {
      joke.value = message()
      reading.value = fint(mood.value.current)
      pointerRotateTransform.'@transform' = "rotate(-${fint(MAX - mood.value.current)})"
      toSVGFragment pointerRotateTransform, joke, reading
    }
  }

  def happier = {-&gt;
    synchronized (this) {
      mood.happier()
    }
  }

  def sadder = {-&gt;
    synchronized (this) {
      mood.sadder()
    }
  }

  def neutraller = {
    synchronized (this) {
      mood.neutraller()
    }
  }

  private fint = { v -&gt;
    String.format("%d", (int)v)
  }

  private message = {-&gt;
    switch (mood.value.current) {
      case TOP_QUAD: return "Wow...what's in the collective waters today :-)"
      case HIGH_QUAD: return "The world seems to be going swimmingly...so far, anyway."
      case HMAX: return "Keep on in that Groove, guys."
      case LOW_QUAD: return "You need a joke: ${jokeService.joke()}"
      case BOTTOM_QUAD: return "Oh dear! We all need a group session with a psycho-therapist, it seems."
      default: return "???"
    }
  }

  private toSVG = {n -&gt;
    def writer = new StringWriter()
    def xnp = new XmlNodePrinter(new PrintWriter(writer))
    xnp.setNamespaceAware true
    xnp.setPreserveWhitespace false
    xnp.print(n)
    writer.getBuffer().toString().trim()
  }

  private toSVGFragment = {Object ... elems -&gt;
    def s = new StringBuilder("&lt;frag&gt;")
    elems.each { s &lt;&lt; toSVG(it) }
    s &lt;&lt; "&lt;/frag&gt;"
    s
  }
}

class Mood {
  private final BIG_JUMP = 20
  private final SMALL_JUMP = 10

  private final randFromOne = RandomUtils.&amp;random.curry(1)
  private final bigRandom = randFromOne.curry(BIG_JUMP)
  private final smallRandom = randFromOne.curry(SMALL_JUMP)

  final value

  Mood(m) {
    value = new RangedValue(range: m.range)
  }

  def happier = {-&gt;
    value.current += bigRandom()
  }

  def sadder = {-&gt;
    value.current -= bigRandom()
  }

  def neutraller = {-&gt;
    // force value toward center
    switch (value.current) {
      case { it &gt; value.middle }: value.current -= smallRandom(); break
      case { it &lt; value.middle }: value.current += smallRandom(); break
      default: break /* do nothing */
    }
  }
}

class RangedValue {
  final range
  final middle
  def current

  RangedValue(m) {
    this.range = m.range
    this.middle = this.current = mid(m.range)
  }

  public void setCurrent(v) {
    switch (v) {
      case { it &gt; range.to }: current = range.to; break
      case { it &lt; range.from }: current = range.from; break;
      default: current = v; break
    }
  }

  private static mid = {r -&gt;
    return (r.to - r.from) / 2
  }
}</pre>
<p>Listing 4: The Grails service and associated classes</p>
<p>This service class has a number interesting points worth noting.</p>
<p>The initialise closure is defined to permit configuration of which SVG file to use via the Grails bootstrap, as shown in Listing 5.</p>
<pre>import org.codehaus.groovy.grails.commons.ApplicationHolder as AH

class BootStrap {

  def drawingService

  def init = {servletContext -&gt;
    def file = "${AH.application.parentContext.getResource('images/').file}${File.separatorChar}GrIMMiS.svg"

    drawingService.initialise file
  }
  def destroy = {
  }
}</pre>
<p>Listing 5: The modified Grails Bootstrap.groovy class</p>
<p>Note the use of Grails&#8217; ApplicationHolder class, which lets us discover the location of the images folder. This is much better than using some hard-coded path.</p>
<p>The initialise closure also pre-resolves the various dynamic elements of the drawing so that they can be easily manipulated by other code later. I&#8217;ll be the first to agree that this is a micro-level performance optimization, but one that I found became important as the size of an image (and also the number of dynamic elements) increased.</p>
<p>As the saying goes [6]: &#8220;Nothing makes you want Groovy more than XML&#8221;, and initialise lets you see Groovy&#8217;s superb XML-handling capabilities first-hand. For example, the following navigates through the SVG document to find the unique g element with id attribute value equal to ‘pointerRotateTransform&#8217;:</p>
<pre>document.g.g.g.find { it.'@id' == 'pointerRotateTransform' }</pre>
<p>The first of the two of the major methods in Listing 4 is svg. This method is responsible for writing the entire SVG document as a string (which is of course eventually returned to the client browser as part of the XHTML document produced by the GSP shown in Listing 2).</p>
<p>Note that svg always writes the most up-to-date state of the SVG document so that a new client retrieves an accurate representation of the meter&#8217;s value right from the start. The alternative approach would be to write the original (as-stored-on-disk) image document to the client and then wait for a refresh to occur. Although possibly simpler and less server-side resource intensive, I have found this alternative to be a generally unsatisfactory approach. It becomes even more so as the image increases in size and complexity (remember that GrIMMiS after all <em>is</em> only a trivial example application), or the drawing poll rate becomes longer.</p>
<p>The second major method in the service is poll. This method is responsible for updating the underlying SVG document to reflect the changing mood of &#8220;the Internet,&#8221; as well as for generating an XML document fragment containing only the updated elements of the image. An example of the document fragment produced is shown here:</p>
<pre>&lt;frag&gt;
  &lt;g xmlns="http://www.w3.org/2000/svg" id="pointerRotateTransform" transform="rotate(-136)"&gt;
    &lt;line x1="0" y1="0" x2="150" y2="0" fill="yellow" stroke="yellow" stroke-width="15" stroke-linecap="round"/&gt;
  &lt;/g&gt;
  &lt;text xmlns="http://www.w3.org/2000/svg" x="300" y="240" id="joke"&gt;
    Oh dear! We all need a group session with a psycho-therapist, it seems.
  &lt;/text&gt;
  &lt;text xmlns="http://www.w3.org/2000/svg" x="300" y="220" id="reading" class="bold"&gt;
    44
  &lt;/text&gt;
&lt;/frag&gt;</pre>
<p>The method poll makes use of a simple helper method called toSVGFragment. If you look at toSVGFragment, you can see that I have made good use of Groovy&#8217;s simple varargs facility to define a method capable of handling an arbitrary number of SVG elements in one invocation. This again helps the DRY-ness of the code and aids development and maintainability: the need to render an additional dynamic element is easily met by simply adding that element to the parameters passed toSVGFragment. There is no need to take alternative, less direct, approaches such as passing parameters as lists or maps, or to define toSVGFragment to take some arbitrary number of (mostly default) parameters.</p>
<p>DrawingService makes effective use of Groovy&#8217;s ranges. Listing 6 (excerpted from Listing 4) shows how I split the range from 0 to 180 into four equal-sized, non-overlapping subranges that corresponding to the angle of the meter&#8217;s pointer. These subranges are then used in conjunction with Groovy&#8217;s excellent switch statement to determine an appropriate message to display.</p>
<pre>final MAX = 180
final QMAX = MAX / 4
final DMAX = MAX / 2
final BOTTOM_QUAD = 0..&lt;QMAX
final LOW_QUAD = QMAX..&lt;DMAX
final HIGH_QUAD = DMAX + 1..&lt;(DMAX + QMAX)
final TOP_QUAD = (DMAX + QMAX)..MAX

private message = {-&gt;
  switch (constrain(mood)) {
    case TOP_QUAD: return "Wow...what's in the collective waters today :-)"
    case HIGH_QUAD: return "The world seems to be going swimmingly...so far, anyway."
    case DMAX: return "Keep on in that Groove, guys."
    case LOW_QUAD: return "You need a joke: ${jokeService.joke()}"
    case BOTTOM_QUAD: return "Oh dear! We all need a group session with a psycho-therapist, it seems."
    default: return "???"
  }
}</pre>
<p>This excerpt also shows how the JokeService is used. Listing 6 shows this trivial class.</p>
<pre>class JokeService {

  boolean transactional = false

  private jokes = [
          /Q: What's yellow and dangerous? A: shark-infested custard!/,
          'The only culture in Australia is found in its youghurts.',
          'When someone emigrates from NZ to Oz, the IQ of both countries goes up.'
  ]

  def joke = {-&gt;
    return jokes[RandomUtils.random(0, jokes.size())]
  }
}</pre>
<p>Listing 6: The JokeService class</p>
<p>Of course, a more sophisticated implementation would pull jokes from a database or perhaps an Internet WebService.</p>
<p>Fancy some curry? In keeping with the slightly gastronomic theme to this article, the Mood class makes use of a technique called currying.</p>
<p>Currying is a functional programming technique that lets you create a new closure based on an existing closure where one parameter is pre-loaded and fixed with a given value (there is a long and very boring formal definition of currying on Wikipedia [7], but this will do).</p>
<p>Rather than having calls to the general-purpose RandomUtils.random closure dotted around my code using (nearly) the same set of parameters at each call, you can see how I successively fix parameters in place to obtain a group of specialized closures perfectly adapted for Mood&#8217;s specific needs:</p>
<pre>final randFromOne = RandomUtils.&amp;random.curry(1)

final bigRandom = randFromOne.curry(BIG_JUMP)

final smallRandom = randFromOne.curry(SMALL_JUMP)</pre>
<p>The specialized closures are used throughout the DrawingService class. This is a very powerful technique that can help simplify your code and improve its readability.</p>
<p>Time for a bit of pop philosophy! The Mood class embodies GrIMMiS&#8217; business rules, such as they are. The philosophy embodied here is that although one is easily capable of saying &#8220;I am emotional,&#8221; it is extremely hard to definitely quantify emotion. Mood thus uses a random number for each operation. When a user hits the happy or sad smiley button, a value taken from a large random range is used (the thinking is that client <em>X</em> could be very happy, while client <em>Y</em> only mildly sad). A user that presses the neutral smiley face is presumed to be less subject to wild &#8220;mood swings&#8221; and so the value used is taken from a smaller random range.</p>
<p>One more point of interest in this code is the use of Groovy&#8217;s ‘&amp;&#8217; operator: this takes a reference to a method and treats it as a closure (so that it can be subsequently curried, for instance, as shown in the above excerpt).</p>
<p>For completeness, Listing 7 shows RandomUtils, a tiny helper class in src/groovy.</p>
<pre>public class RandomUtils {
  private static final rg = new Random()

  public static int random(off, lim) {
    off + rg.nextInt(lim)
  }
}</pre>
<p>Listing 7: The RandomUtils class</p>
<p>The following snippet taken from the RangedValue class shows how I have used an explicit setter for the derived property current (the Groovy automatically-supplied getter continues to be used as normal). The supplied setter method ensures that current is maintained within the bounds of the range defined for it at construction.</p>
<pre>
def current

public void setCurrent(v) {
  switch (v) {
    case { it &gt; range.to }: current = range.to; break
    case { it &lt; range.from }: current = range.from; break
    default: current = v; break
  }
}
</pre>
<p>Both JokeService and DrawingService are marked as non-transactional. This is clearly appropriate and may help to conserve server-side resources.</p>
<p>The final point to note from Listing 4 concerns the various synchronized blocks that you will see in the code. In contrast to a controller, which typically has many active instances (usually one instance per request), a service by default is a singleton: there is only one instance regardless of how many controllers are trying to use it. This is quite appropriate here: the drawingService should only maintain a single SVG drawing, regardless of however many clients are using GrIMMiS. The singleton nature of drawingService does mean that many operations (such as updating the current mood value, or modifying the server-side SVG diagram to reflect that mood) should be carried out in a serialized manner to avoid possible mis-correspondence of mood value and rotation transform value or message.</p>
<h1>Wrapping Up</h1>
<p>I hope you enjoyed taking a look at the recipe for this little entrée.</p>
<p>Recall that I started to make this dish because I wanted to see if Groovy and Grails would make it easier to build an application similar to one I built for a client several years ago using plain Java. It is clear that Groovy&#8217;s superb XML support and simpler file handling has improved things. It is also clear that features like varargs and currying have let me produce much more maintainable code. By providing a clean web-based environment, with interceptors and effective support for JavaScript libraries (such as prototype), Grails has made it possible for me to write <em>much</em> better code than before. In general, even when taking into account the significantly smaller size and reduced capabilities, this application has a cleaner, more comprehensible feel to it.</p>
<p>I wish I&#8217;d had these &#8220;Gr8 technologies&#8221; available to me many years ago!</p>
<h1>Learn More</h1>
<ol>
<li>The origin of the term ‘AJAX&#8217;, <a href="http://en.wikipedia.org/wiki/Ajax_(programming)">http://en.wikipedia.org/wiki/Ajax_(programming)</a></li>
<li>SVG support matrix for the various browsers, <a href="http://www.codedread.com/svg-support.php">http://www.codedread.com/svg-support.php</a></li>
<li>Google SVG Web, <a href="http://code.google.com/p/svgweb/">http://code.google.com/p/svgweb/</a></li>
<li>RENESIS SVG Plugin for IE, <a href="http://www.examotion.com/index.php?id=product_player">http://www.examotion.com/index.php?id=product_player</a></li>
<li>Yahoo User Interface Blog, <a href="http://yuiblog.com/blog/2006/11/28/performance-research-part-1/">http://yuiblog.com/blog/2006/11/28/performance-research-part-1/</a></li>
<li>Stuff I&#8217;ve learned recently, <a href="http://kousenit.wordpress.com/2008/03/12/nothing-makes-you-want-groovy-more-than-xml/">http://kousenit.wordpress.com/2008/03/12/nothing-makes-you-want-groovy-more-than-xml/</a></li>
<li>Wikipedia: Currying, <a href="http://en.wikipedia.org/wiki/Currying">http://en.wikipedia.org/wiki/Currying</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/04/the-groovy-internet-mood-meter-in-svg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Batch Processing with Spring Batch</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/03/batch-processing-with-spring-batch/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/03/batch-processing-with-spring-batch/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 10:44:23 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=688</guid>
		<description><![CDATA[I have blathered on about Spring Batch a few times in the past.
The June 2009 edition of GroovyMag carried my article on how to use Spring Batch with Groovy; it&#8217;s republished (with permission) here. This was my second article for GroovyMag, I have also republished  the first one, on Spring Integration with Groovy. 
As [...]]]></description>
			<content:encoded><![CDATA[<p>I have blathered on about Spring Batch a <a href="http://wordpress.transentia.com.au/wordpress/2009/06/06/groovymag-june-issue…now-80-bob-brown-free/">few</a> <a href="http://wordpress.transentia.com.au/wordpress/2009/06/16/springsource-toolsuite-21-supports-spring-batch/">times</a> in the past.</p>
<p>The June 2009 edition of <a href="http://groovymag.com/">GroovyMag</a> carried my article on how to use Spring Batch with Groovy; it&#8217;s republished (with permission) here. This was my second article for GroovyMag, I have also <a href="http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/">republished  the first one, on Spring Integration with Groovy</a>. </p>
<p>As I lurk on the Groovy and Grails mailing lists, I see a real need &#8220;out there&#8221; for this sort of infrastructure. Hopefully, this article will contribute to a small improvement in awareness. Writing code should, after all, be the <a href="http://www.azlyrics.com/lyrics/eagles/thelastresort.html">last resort</a> and not the first&#8230;</p>
<p>The source code is available, <a href="/wordpress/wp-content/uploads/2010/02/groovymag-spring-batch.zip">of course</a>!</p>
<hr />
<img src="/wordpress/wp-content/uploads/2009/06/gm8_400.jpg" alt="" /></p>
<p><strong>Batch Processing with Spring Batch<br />
Dealing with Large Volumes of Data using Spring Batch and Groovy</strong></p>
<p><em>Even though a major focus of modern ideas such as Service Oriented Architectures and Software As A Service is to facilitate and enhance live interactions between systems, batch processing remains as important and widely-used as ever: practically every significant project contains a batch processing component. Until the arrival of Spring Batch (version 1.0 was released in March, 2008), no widely available, open source, reusable architecture framework for batch processing had existed; batch processing had always been approached on an ad-hoc basis. This article will examine how Groovy joins with Spring Batch to ease the pain of dealing with large data sets.</em></p>
<h1>A Brief Overview of Spring Batch</h1>
<p>Spring Batch (SB) is a relatively new member of the Spring family of technologies. There is no better introduction than this excerpt from the documentation (see the &#8220;Learn More&#8221; section for the URL):</p>
<p style="padding-left: 30px;">Spring Batch is a lightweight, comprehensive batch framework designed to enable the development of robust batch applications . . . Spring Batch builds upon the productivity, POJO-based development approach, and general ease of use capabilities people have come to know from the Spring Framework, while making it easy for developers to access and leverage more advance [sic] enterprise services when necessary . . . Spring Batch provides reusable functions that are essential in processing large volumes of records, including logging/tracing, transaction management, job processing statistics, job restart, skip, and resource management. It also provides more advance technical services and features that will enable extremely high-volume and high performance batch jobs though optimization and partitioning techniques. Simple as well as complex, high-volume batch jobs can leverage the framework in a highly scalable manner to process significant volumes of information.</p>
<p>SB provides a great deal of out-of-the-box functionality: very flexible adapters for reading from flat files, facilities for dealing with JMS queues, JDBC-based database adapters (of course), along with a simple workflow ability allowing conditional, repetitive and parallel processing. Sophisticated error handling/recovery capabilities and simple job control round out the package. Following the standard Spring Framework convention of &#8220;don&#8217;t reinvent the wheel,&#8221; SB does not include a complete set of scheduling/job control tools, but works instead in conjunction with existing Spring-friendly schedulers such as Quartz and Tivoli. Over time, SB will make more use of other members of the Spring family and in particular Spring Integration, and this pairing in particular should make for a formidable partnership.</p>
<p>SB was seeded and driven by technology and developers from Accenture–as well as SpringSource and the general Open Source community–and so claims to represent the distillation of a fair bit of experience with &#8220;real world&#8221; needs and situations.</p>
<h1>A Small Example Application</h1>
<p>Because SB is rooted in the standard Spring Framework, it is quite compatible with Groovy (and is also simple to integrate into Grails). As a demonstration, I&#8217;ll implement a simple batch processing job, as follows: read and parse an input data file (where each record is formatted according to a custom multiline format); validate each record (rejecting invalid records and writing the relevant record to a dump file); apply a specific transformation to each remaining (valid) record; and finally, write the valid, transformed data into an XML file.</p>
<p>Figure 1 provides a simplified, high-level view of the application&#8217;s overall workflow.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/02/figure_1.png" alt="figure_1" title="figure_1" width="828" height="423" class="alignnone size-full wp-image-701" /><br />
Figure 1: Simplified, high-level view of the workflow in the example application</p>
<p>Figure 1 shows how an application initiates a SB job. The job is composed of a number of steps, which are themselves composed of a number of substeps or tasklets. Tasklets are the building blocks of the application and may read/write/validate/transform or otherwise ‘munge&#8217; the data.</p>
<p>Even though this is a very simple batch-processing task, there are a number of tricky areas. Consider the input data file format (an example is shown in Listing 1): this format contains data split into logical sections (customer ID, contact information, credit card information, customer balance), with one section to a line. Each line is a CSV-formatted record but some fields may themselves contain fixed-width records. The whole record is &#8220;book-ended&#8221; by BEGIN/END markers, each of which must have the same record number. The first two lines of the file are free-form commentary.</p>
<pre>
; this is a nasty file format
; it's going to be a challenge to process!
BEGIN0000000001
CUST,9876543210
CONT,0416123456,0712340987,fred@nowhere.com
CARD,visa:1234 1234 4321 4321:000
BAL,1000.00
END0000000001
</pre>
<p>Listing 1: Example input data record</p>
<p>Processing this data file is going to be quite a challenge and it is probably worth taking some time to consider how you would tackle this task in plain Java or Groovy.</p>
<p>It is safe to assume that the input data will contain numerous errors that makes validation and error handling a priority consideration for this application. Validation is a common necessary chore that is not difficult but is tedious and error-prone; by relying on standard Spring technologies, SB helps simplify this task.</p>
<p>Another minor challenge is concerned with producing the output XML document. Listing 2 shows how the record given in should be written.</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;customers>
  &lt;customer sequence="0000000001">
    &lt;id>9876543210&lt;/id>
    &lt;mobile>0416123456&lt;/mobile>
    &lt;landline>0712340987&lt;/landline>
    &lt;email>fred@nowhere.com&lt;/email>
    &lt;provider>visa&lt;/provider>
    &lt;number>1234 1234 4321 4321&lt;/number>
    &lt;security>000&lt;/security>
    &lt;balance>1010.0&lt;/balance>
  &lt;/customer>
&lt;/customers>
</pre>
<p>Listing 2: The resultant XML-formatted data record</p>
<p>As is always the case with infrastructures and frameworks, one often gets the feeling of overkill when working with a simple example such as the one in this article. Keep in mind however that as a problem gets bigger, a framework becomes more and more necessary. Remember also that SB was written with these large problem spaces in mind and so you may have difficulty seeing SB&#8217;s full potential using this one simple example application.</p>
<h2>The Driver Application</h2>
<p>The example application uses a small command-line application to kick off the real batch job. SB actually provides a simple command-line launcher to do this, but it is instructive to see how to deal with a SB job by hand. As Listing 3 shows, the launcher is very simple and is a typically simple Spring Framework-aware application.</p>
<pre>
package au.com.transentia.sb

import o.s.batch.core.JobParametersBuilder
import o.s.context.support.ClassPathXmlApplicationContext

public class SpringBatch {

  public static void main(String[] args) {
    def context =
      new ClassPathXmlApplicationContext(['applicationContext.xml', 'job.xml'] as String[], true)

    def jobLauncher = context.getBean('jobLauncher')

    def job = context.getBean('job')

    def adjustmentPercent = 1.01D;

    def jobExecution =
      jobLauncher.run(job,
        new JobParametersBuilder().
          addDouble("adjustment.percent", adjustmentPercent).toJobParameters())
    jobExecution.with {
      println """
Job: $jobId
StartTime: $startTime; EndTime: $endTime
Duration: ${endTime.time - startTime.time} ms
Status=$exitStatus
"""
      stepExecutions.each { println "STEP: $it" }
    }
  }
}
</pre>
<p>Listing 3: The Groovy driver application</p>
<p>Note: throughout this article, the package name prefix ‘org.springframework&#8217; is abbreviated to &#8216;o.s&#8217; to reduce line length and aid formatting and readability.</p>
<p>Of interest here is the creation of the Spring application context. The application is looking for two files on its classpath: applicationContext.xml defines the boilerplate SB infrastructure and job.xml defines the SB job itself. This is a standard Spring development technique. I&#8217;ll look at these files in more detail later.</p>
<p>The job instance is created by the Spring application context and is looked up by the application itself; this is the real meat of the batch definition, as we shall see.</p>
<p>The jobLauncher instance obtained from the application context is part of SB. As the name suggests, it is concerned with mediating access to a SB job instance. In this case, it will control execution of the job instance defined in job.xml and retrieved by the application. The joblauncher.run() method returns a SB jobExecution instance that allows the application to determine the state of the associated job and its composite steps.</p>
<p>JobParametersBuilder provides a way of defining a map of parameters that can be passed into a job and subsequently accessed by the various steps and tasklets.</p>
<p>Listing 4 shows (slightly edited) the application in action.</p>
<pre>
Job: 0
StartTime: Fri May 01 16:25:50 EST 2009; EndTime: Fri May 01 16:25:54 EST 2009
Duration: 3117 ms
Status=exitCode=COMPLETED;exitDescription=
STEP: StepExecution: id=0, name=startupStep, status=COMPLETED,. . .
STEP: StepExecution: id=1, name=processStep, status=COMPLETED,. . .
STEP: StepExecution: id=2, name=endingStep, status=COMPLETED, exitStatus=COMP. . .
</pre>
<p>Listing 4: Output from executing the application</p>
<h2>Boilerplate Configuration</h2>
<p>SB requires a certain amount of standard configuration to be put in place in preparation for job execution. </p>
<p>Listing 5 excerpts the relevant portion of the applicationContext.xml file that contains this configuration.</p>
<pre>
&lt;bean id="transactionManager"
      class="o.s.batch.support.transaction.ResourcelessTransactionManager"/>

&lt;bean id="jobRepository"
      class="o.s.batch.core.repository.support.MapJobRepositoryFactoryBean"
      p:transactionManager-ref="transactionManager"/>

&lt;bean id="jobLauncher"
      class="o.s.batch.core.launch.support.SimpleJobLauncher"
      p:jobRepository-ref="jobRepository" />
</pre>
<p>Listing 5: Minimal-functionality SB configuration</p>
<p>This is the least sophisticated SB configuration possible. This configuration establishes a no-op transaction manager and a pure in-memory jobRepository. The latter configuration option means that no distribution, persistence or job restart capabilities are available. For the purposes of this application, this configuration is sufficient.</p>
<p>In this example application, all processing is sequential and synchronous with the application; however, it is possible to configure the jobLauncher instance to execute a job asynchronously to the application. An asynchronous configuration would be appropriate if using SB in conjunction with a Grails/AJAX application, which could initiate a job and then poll for status and update a visual progress indicator until the job completes.</p>
<h2>The Job Definition</h2>
<p>The keystone of this application is actually the job.xml application context file. Because this is quite long, I will go through it in sections.</p>
<p>Note: The listings shown here have been edited and excerpted to save space (while hopefully remaining clear). </p>
<p>The full source code for this example is supplied with this edition of GroovyMag, of course.</p>
<p>Listing 6 shows the place where it all begins: the job definition.</p>
<pre>
&lt;batch:job id="job">
  &lt;batch:step id="startupStep" next="processStep">
    &lt;batch:tasklet ref="logStartupMessage"/>
  &lt;/batch:step>
  &lt;batch:step id="processStep" next="endingStep">
    &lt;batch:tasklet>
      &lt;batch:chunk skip-limit="100000"
                   reader="itemReader"
                   writer="itemWriter"
                   processor="compositeItemProcessor"
                   commit-interval="1">
        &lt;batch:streams>
          &lt;batch:stream ref="errorItemWriter"/>
        &lt;/batch:streams>
        &lt;batch:skippable-exception-classes>
          o.s.batch.item.file.FlatFileParseException
          o.s.batch.item.validator.ValidationException
        &lt;/batch:skippable-exception-classes>
      &lt;/batch:chunk>
      &lt;batch:listeners>
        &lt;batch:listener ref="skipListener"/>
      &lt;/batch:listeners>
    &lt;/batch:tasklet>
  &lt;/batch:step>
  &lt;batch:step id="endingStep">
    &lt;batch:tasklet ref="logEndingMessage"/>
  &lt;/batch:step>
&lt;/batch:job>
</pre>
<p>Listing 6: The job definition</p>
<p>This definition constructs a three-stage processing pipeline.While the first and last steps merely print a status message, the middle step (with id=processStep) is the most important and what I focus on here. The processStep step identifies the various input and output processors and also defines the intermediate transformations/processes that will be executed on each record.</p>
<p>An important SB concept introduced here is that of a chunk. A chunk defines the processing that is to be done within a transaction boundary: a batch of records that may be written/rolled-back as a whole, for instance. For this application, each record is treated as constituting a separate chunk and so error handling, etc., is done on a per-record basis.</p>
<p>The batch:streams, batch:listeners and batch:skippable-exception-classes configuration elements are all related to the way that erroneous input records are handled. This will be looked at later.</p>
<h3>Processing Step One: Input</h3>
<p>Listing 7 defines the itemReader bean (and some of the necessary associated configuration), which deals with reading and parsing the multiline record from the input data file.</p>
<pre>
&lt;bean id="rawDataResource" class="o.s.core.io.FileSystemResource">
  &lt;constructor-arg value="resource/data/inputdata.dat"/>
&lt;/bean>

&lt;bean id="itemReader" class="au.com.transentia.sb.MultilineRecordReader">
  &lt;property name="flatFileItemReaderDelegate">
    &lt;bean class="o.s.batch.item.file.FlatFileItemReader"
          p:resource-ref="rawDataResource"
          p:linesToSkip="2">
      &lt;property name="lineMapper">
        &lt;bean class="o.s.batch.item.file.mapping.DefaultLineMapper"
            p:lineTokenizer-ref="multilineFileTokenizer">
          &lt;property name="fieldSetMapper">
            &lt;bean class="o.s.batch.item.file.mapping.PassThroughFieldSetMapper"/>
          &lt;/property>
        &lt;/bean>
      &lt;/property>
    &lt;/bean>
  &lt;/property>
&lt;/bean>

&lt;bean id="multilineFileTokenizer"
  class="o.s.batch.item.file.transform.PatternMatchingCompositeLineTokenizer">
  &lt;property name="tokenizers">
    &lt;map>
      &lt;entry key="BEGIN*" value-ref="beginLineTokenizer"/>
      &lt;entry key="CUST*" value-ref="customerLineTokenizer"/>
      &lt;entry key="CONT*" value-ref="contactLineTokenizer"/>
      &lt;entry key="CARD*" value-ref="cardLineTokenizer"/>
      &lt;entry key="BAL*" value-ref="balanceLineTokenizer"/>
      &lt;entry key="END*" value-ref="endLineTokenizer"/>
    &lt;/map>
  &lt;/property>
&lt;/bean>

&lt;bean id="csvLineTokenizer"
   class="o.s.batch.item.file.transform.DelimitedLineTokenizer"
   p:delimiter=","
   abstract="true"/>

&lt;bean id="fixedLineTokenizer"
      class="o.s.batch.item.file.transform.FixedLengthTokenizer"
      p:names="SKIP,sequence"
      abstract="true"/>

&lt;!--BEGIN0000000000-->
&lt;bean id="beginLineTokenizer"
      parent="fixedLineTokenizer"
      p:columns="1-5,6-"/>

&lt;!--END0000000000-->
&lt;bean id="endLineTokenizer"
      parent="fixedLineTokenizer"
      p:columns="1-3,4-"/>

&lt;!--CUST,9876543210-->
&lt;bean id="customerLineTokenizer"
      parent="csvLineTokenizer"
      p:names="SKIP,id"/>
</pre>
<p>Listing 7: Input record handling</p>
<p>Take your time to read through this code; the itemReader is quite a sophisticated piece of infrastructure.<br />
As you piece things together, you will see how almost everything is delegated to standard SB classes: the actual reading of the file and skipping the comment lines is deferred to a FlatFileItemReader, and the recognition and handling of the various logical sections in a record are handled by the PatternMatchingCompositeLineTokenizer class (which itself defers to a number of line tokenizers). In fact, the only custom activity here is the mapping of the parsed data to a simple application-specific class via the au.com.transentia.sb.MultilineRecordReader class. A tremendous amount of processing is being performed here with very little development effort.</p>
<p>Note how the use of abstract parent definitions (e.g., fixedLineTokenizer), makes it possible to write clearer configurations for several elements (e.g., beginLineTokenizer/endLineTokenizer). This is a standard Spring technique that helps to keep the configuration file DRY (i.e., without unnecessary repetition).</p>
<p>Again, consider how much effort would be involved if you had to do all this by hand.</p>
<p>Listing 8 and Listing 9 shows the MultilineRecord and MultilineRecordReader classes.</p>
<pre>
package au.com.transentia.sb

public class MultilineRecord {
  String sequence
  String endSequence

  Long id

  String mobile
  String landline
  String email

  String provider
  String number
  String security

  BigDecimal balance

  @Override public String toString() { …elided… }
}
</pre>
<p>Listing 8: The MultilineRecord class</p>
<pre>
package au.com.transentia.sb

import …elided…

public class MultilineRecordReader implements
  ItemReader&lt;MultilineRecord>, ItemStream {
  private FlatFileItemReader&lt;FieldSet> flatFileItemReaderDelegate

  public MultilineRecord read() throws Exception
  {
    MultilineRecord mlr = null

    // flags to indicate the presence of component lines
    def customerSeen = false;
    def contactsSeen = false
    def ccSeen = false
    def balSeen = false

    def line
    while (line = this.flatFileItemReaderDelegate.read())
    {
      String prefix = line.readString(0);
      switch (prefix)
      {
        case 'BEGIN':
          mlr = new MultilineRecord(sequence: line.readString(1))
          break

        default:
          Assert.notNull(mlr, "MultilineRecord not yet intialised")
          switch (prefix)
          {
            case 'CUST':
              mlr.id = line.readLong(1)
              customerSeen = true
              break

            case 'CONT':
              mlr.with {
                mobile = line.readString(1)
                landline = line.readString(2)
                email = line.readString(3)
              }
              contactsSeen = true
              break

            case 'CARD':
              mlr.with {
                provider = line.readString(1)
                number = line.readString(2)
                security = line.readString(3)
              }
              ccSeen = true
              break

            case 'BAL':
              mlr.balance = line.readBigDecimal(1)
              balSeen = true
              break

            case 'END':
              // check all record fields seen
              Assert.isTrue(mlr &#038;&#038; customerSeen &#038;&#038;
                            contactsSeen &#038;&#038; ccSeen &#038;&#038; balSeen,
                  "Incomplete Record Found")
              mlr.endSequence = line.readString(1)
              return mlr
              break
          }
      }
    }
    null
  }

  … elided …
}
</pre>
<p>Listing 9: The MultilineRecordReader class</p>
<p>The MultilineRecordReader class is responsible for allocating the various fields of each tokenized line (offered as SB FieldSets) to a single new instance of a MultilineRecord. It also performs some minor validation to ensure that there are no missing logical sections. Note how Groovy&#8217;s versatile switch statement and the use of Groovy&#8217;s enhanced Object with method makes the processing much clearer than it would be in plain Java.</p>
<h3>Processing Step Two: Output</h3>
<p>As every first-year CompSci student learns, after input comes processing, followed by output. Naturally, I am not going to follow this sequence! In an attempt to achieve a less convoluted narrative, I&#8217;ll now look at output processing (the third stage of the processStep step). Listing 10 shows the requisite configuration for the itemWriter.</p>
<pre>
&lt;bean id="itemWriter"
      class="o.s.batch.item.xml.StaxEventItemWriter"
      p:resource-ref="processedOutputResource"
      p:marshaller-ref="multiLineRecordMarshaller" p:rootTagName="customers"
      p:overwriteOutput="true"/>

&lt;bean id="multiLineRecordMarshaller" class="o.s.oxm.xstream.XStreamMarshaller">
  &lt;property name="useAttributeFor">
    &lt;map>
      &lt;entry key="sequence">
        &lt;value type="java.lang.Class">java.lang.String&lt;/value>
      &lt;/entry>
    &lt;/map>
  &lt;/property>
  &lt;property name="omittedFields">
    &lt;map>
      &lt;entry key="au.com.transentia.sb.MultilineRecord" value="endSequence"/>
    &lt;/map>
  &lt;/property>
  &lt;property name="aliases">
    &lt;map>
      &lt;entry key="customer"
             value="au.com.transentia.sb.MultilineRecord"/>
    &lt;/map>
  &lt;/property>
&lt;/bean>

&lt;bean id="processedOutputResource" class="o.s.core.io.FileSystemResource">
  &lt;constructor-arg value="resource/data/job-output.xml"/>
&lt;/bean>
</pre>
<p>Listing 10: Output XML processing</p>
<p>The itemWriter configuration is quite straightforward. Output handling is actually delegated to a marshaller instance. In this case, the Spring OXM project is brought to bear to simplify XML generation. The XStreamMarshaller is only very minimally configurable (but quite performant…the age-old tradeoff): it is possible to render the sequence field as an XML attribute and not to render the endSequence field at all, but that is pretty much all the configuration possible.</p>
<h3>Processing Step Three: Validation and Transformation</h3>
<p>Now that we&#8217;ve seen the mechanics of writing a file, it is time to move on to (or more accurately: back to) the middle processing step.</p>
<p>Listing 11 shows the configuration of the processing tasks.</p>
<pre>
&lt;bean id="compositeItemProcessor"
      class="o.s.batch.item.support.CompositeItemProcessor">
  &lt;property name="itemProcessors">
    &lt;list>
      &lt;ref local="validatingItemProcessor"/>
      &lt;ref local="embiggenProcessor"/>
    &lt;/list>
  &lt;/property>
&lt;/bean>

&lt;bean id="validatingItemProcessor"
      class="o.s.batch.item.validator.ValidatingItemProcessor">
  &lt;constructor-arg ref="validator"/>
&lt;/bean>

&lt;bean id="validator"
      class="o.s.batch.item.validator.SpringValidator">
  &lt;property name="validator">
    &lt;bean id="luhnValidator"
          class="o.s.validation.valang.ValangValidator">
      &lt;property name="customFunctions">
        &lt;map>
          &lt;entry key="luhn" value="au.com.transentia.sb.LuhnFunction"/>
        &lt;/map>
      &lt;/property>
      &lt;property name="valang">
        &lt;value>
          &lt;![CDATA[
{ id : ? > 0 :
  'id field must be a natural number' }
{ endSequence : ? is not blank :
  'end sequence number field missing' }
{ sequence : ? is not blank :
  'begin sequence number field missing' }
{ endSequence : endSequence == sequence :
  'mismatched begin/end sequence numbers' }
{ mobile : match('\\d{10}',?) == true :
  'mobile field must be 10 digits' }
{ landline : match('\\d{8,10}',?) == true :
  'landline field must be 8-10 digits' }
{ provider : ? in 'amex', 'visa', 'macd' :
  'card provider field should be one of "visa", "amex" or "macd"' }
{ number : match('\\d{4}[ ]\\d{4}[ ]\\d{4}[ ]\\d{4}',?) == true :
  'card number field must match the format "xxxx xxxx xxxx xxxx"' }
{ number : luhn(?) == true :
  'card number luhn check failed' }
{ security : match('\\d{3}',?) == true :
  'card number field must be 3 digits' }
{ email : ? is not blank :
  'email field missing' }
{ email : email(?) == true :
  'email field is not a valid email address' }
{ balance : ? is not blank :
  'balance field missing' }
]]&gt;
        &lt;/value>
      &lt;/property>
    &lt;/bean>
  &lt;/property>
&lt;/bean>

&lt;bean id="errorOutputResource"
      class="o.s.core.io.FileSystemResource">
  &lt;constructor-arg value="resource/data/errors.txt"/>
&lt;/bean>

&lt;bean id="passthroughLineAggregator"
      class="au.com.transentia.sb.PassThroughLineAggregator"/>

&lt;bean id="errorItemWriter"
      class="o.s.batch.item.file.FlatFileItemWriter"
      p:resource-ref="errorOutputResource"
      p:lineAggregator-ref="passthroughLineAggregator"
      p:shouldDeleteIfExists="true"/>

&lt;bean id="skipListener" class="au.com.transentia.sb.SkipListener"
      p:writer-ref="errorItemWriter"/>

&lt;bean id="embiggenProcessor"
      class="au.com.transentia.sb.EmbiggenProcessor"
      scope="step"
      p:percent="#{jobParameters[adjustment.percent]}"/>
</pre>
<p>Listing 11: Configuration of processing tasks</p>
<p>For this application, the middle processing part of the pipeline is itself a two-stage composite process: first comes validation (and possibly rejection of invalid data), followed by transformation. This is configured through the compositeItemProcessor bean (which is referenced by the processStep step in ).<br />
SB allows the use of any of the available Spring-compatible validation systems. For this example I have chosen to use the Valang Spring module, because of its clear declarative nature.</p>
<p>The validator bean contains a plaintext valang property which defines a series of expressions that should be evaluated against the various properties of the bean to which it is applied. For example:</p>
<pre>
{ id : ? &gt; 0 : 'id field must be a natural number' }
</pre>
<p>If the given expression evaluates to false, validation fails and the associated message is added to the list of errors being maintained by the validator bean.</p>
<p>While Valang provides a series of standard functions (such as email, which checks to ensure that a field contains a valid email address), it cannot account for all possible requirements. It can be augmented via the customFunctions property, however, and it is this ability that allows me to define an application-specific function. To illustrate this, I&#8217;ll introduce a check for the validity of the credit card number field (using the so-called Luhn function; see &#8220;Learn More&#8221; for a reference to how this works), as is shown in Listing 12.</p>
<pre>
package au.com.transentia.sb

import …elided…

public class LuhnFunction extends AbstractFunction {

  public LuhnFunction(Function[] arg0, int arg1, int arg2) {
    super(arg0, arg1, arg2);
    definedExactNumberOfArguments(1);
  }

  @Override
  protected Object doGetResult(Object target) throws Exception {
    def str = getArguments()[0].getResult(target).toString()
    isValid(str)
  }

  public static boolean isValid(String cardNumber) {
    def sum = 0
    def addend = 0
    def timesTwo = false

    cardNumber.replaceAll(' ', '').each {dc ->
      def digit = Integer.valueOf(dc)
      if (timesTwo)
      {
        addend = digit * 2
        if (addend > 9)
          addend -= 9;
      }
      else
        addend = digit
      sum += addend
      timesTwo = !timesTwo
    }

    (sum % 10) == 0
  }
}
</pre>
<p>Listing 12: Luhn function class</p>
<p>This allows the use of the luhn() function as if it were a built-in Valang function:</p>
<pre>
{ number : luhn(?) == true : 'card number luhn check failed' }
</pre>
<p>Valang is a powerful and effective validation framework. Its most important feature is probably that since it uses &#8220;near natural language&#8221; configuration, an application&#8217;s validation rules can be reviewed and changed by any appropriate product owner or business representative and this can make for a higher quality product. Valang is a standalone framework and well worth further study (see the &#8220;Learn More&#8221; section for the URL).</p>
<p>Refer back to Listing 6. You will see that in the event of a ValidationException, processing of a chunk is skipped. This application registers a listener for this situation that simply writes the offending record to a configured itemWriter. Listing 13 shows the appropriate class.</p>
<pre>
package au.com.transentia.sb

import org.springframework.batch.core.listener.SkipListenerSupport

public class SkipListener extends SkipListenerSupport&lt;MultilineRecord, Object> {

  def writer

  @Override
  public void onSkipInProcess(MultilineRecord item, Throwable t) {
    writer.write ( [ item ] )
  }
}
</pre>
<p>Listing 13: Error handling skip listener class</p>
<p>The configured itemWriter has an associated line aggregator that performs preprocessing before the actual write takes place. In this case, the PassThroughLineAggregator class simply performs a toString operation on the presented item, as Listing 14 shows.</p>
<pre>
package au.com.transentia.sb

import org.springframework.batch.item.file.transform.LineAggregator

public class PassThroughLineAggregator implements LineAggregator&lt;MultilineRecord> {
  public String aggregate(MultilineRecord item) {
    item.toString()
  }
}
</pre>
<p>Listing 14: PassThroughLineAggregator class</p>
<p>The second part of the composite processing step shown in deals with transforming the now-valid data record. This particular transformation represents a business rule: as each record is transformed, its balance should be adjusted by a certain percentage. This requires a small piece of Groovy, the EmbiggenProcessor. Listing 15 shows this simple class in its entirety.</p>
<pre>
package au.com.transentia.sb

import org.springframework.batch.item.ItemProcessor

public class EmbiggenProcessor
  implements ItemProcessor&lt;MultilineRecord, MultilineRecord> {

  def percent

  public MultilineRecord process(MultilineRecord mlr) throws Exception {
    mlr.balance *= percent

    mlr
  }
}
</pre>
<p>Listing 15: The EmbiggenProcessor class</p>
<p>If you refer back to Listing 3 and Listing 11, you will see how the percent value is injected into the EmbiggenProcessor class from the application via the job.xml file.</p>
<h2>Performance</h2>
<p>To paraphrase Benjamin Disraeli, first Earl of Beaconsfield: &#8220;there are lies, damn lies and performance measurements.&#8221; Since many batch jobs deal with very large data sets, the performance of SB is bound to be of paramount interest to some. I am a coward! I am going to merely dip my toe into this potentially turbulent topic and just let you know that <em>on my laptop</em>, the complete processing of 42,500 records took 92,381 ms. That makes about 2.17 ms per record. Not too shabby in my opinion–but of course, your mileage may vary.</p>
<h1>Wrapping Up</h1>
<p>You&#8217;ve now walked through a complete SB application. A large proportion of the application is declarative configuration. I like this style of working: it reduces the amount of ‘real&#8217; coding that is required and thus minimizes the opportunity for error. For those parts of the problem space that are not directly covered by the standard components, Groovy has proved to be a very effective tool; with minimal effort and coding, Groovy has allowed me to very effectively concentrate on creating a clear solution, which also minimizes the opportunity to introduce bugs.</p>
<p>I continue to find it impressive that Groovy—a dynamic language—can still effectively work with highly-typed interfaces such as those exposed by SB: checked exceptions, strongly typed parameter lists, and even generic classes can be handled with ease. At the same time, Groovy can let me work with frameworks such as Valang without forcing me to deal with ‘nasties&#8217; such as adapter classes, proxies, out-of-process adapters, etc. This means that an inveterate Java programmer like myself can continue to apply his existing skillset—with its hard-won collection of lessons learned, tricks and tips picked up over time—while also taking advantage of the productivity and ease of use of Groovy&#8217;s modern dynamic language. In my not-so-humble opinion, this is important and will surely contribute to a rapid increase in Groovy&#8217;s popularity.</p>
<h1>Learn More</h1>
<dl>
<dt>Spring Batch</dt>
<dd><a href="http://static.springsource.org/spring-batch/">http://static.springsource.org/spring-batch/</a></dd>
<dt>Spring Valang module</dt>
<dd><a href="https://springmodules.dev.java.net/">https://springmodules.dev.java.net/</a></dd>
<dt>Spring OXM</dt>
<dd><a href="http://static.springframework.org/spring-ws/sites/1.5/reference/html/oxm.html">https://springmodules.dev.java.net/</a></dd>
<dt>The Luhn Function</dt>
<dd><a href="http://www.merriampark.com/anatomycc.htm">http://www.merriampark.com/anatomycc.htm</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/03/batch-processing-with-spring-batch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MarkupBuilder, How Do I love Thee&#8230;</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/02/03/markupbuilder-how-do-i-love-thee/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/02/03/markupbuilder-how-do-i-love-thee/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 01:09:43 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=677</guid>
		<description><![CDATA[In oh, so many ways!
Groovy&#8217;s MarkupBuilder class can really clean up your code.

import groovy.xml.*

def out = new StringWriter()
def b = new MarkupBuilder(out)
b.table(id: 'test', border: 0) {
  tbody {
    tr {
      td "hello"
      td(id: 'hello_id', 'hello')
      td(id: [...]]]></description>
			<content:encoded><![CDATA[<p>In oh, so many ways!</p>
<p>Groovy&#8217;s <a href="http://groovy.codehaus.org/api/groovy/xml/MarkupBuilder.html">MarkupBuilder</a> class can really clean up your code.</p>
<pre>
import groovy.xml.*

def out = new StringWriter()
def b = new MarkupBuilder(out)
b.table(id: 'test', border: 0) {
  tbody {
    tr {
      td "hello"
      td(id: 'hello_id', 'hello')
      td(id: 'test', /hello/)
      td(id: 'esc') { mkp.yield '&amp;nbsp;' }
      td(id: 'unesc') { mkp.yieldUnescaped '&amp;nbsp;' }
      td(id: 999) { mkp.yield 999 }
      td(id: 99) { mkp.yieldUnescaped 99 }
      td(id: 88) { mkp.yieldUnescaped 'hello' }
      td(id: 77) { mkp.yieldUnescaped "hello2" }
      td(id: 66) { mkp.yieldUnescaped """hello3""" }
      // gives compilation error "unexpected token: } at line: 19, column: 48":
      //   td(id: 55) { mkp.yieldUnescaped /hello4/ }
      td(id: 55) { mkp.yieldUnescaped "" + /hello4/ }
    }
  }
}

println out.toString()
</pre>
<p>This produces:</p>
<pre>
&lt;table id='test' border='0'>
  &lt;tbody>
    &lt;tr>
      &lt;td>hello&lt;/td>
      &lt;td id='hello_id'>hello&lt;/td>
      &lt;td id='test'>hello&lt;/td>
      &lt;td id='esc'>&amp;nbsp;&lt;/td>
      &lt;td id='unesc'>&nbsp;&lt;/td>
      &lt;td id='999'>999&lt;/td>
      &lt;td id='99'>99&lt;/td>
      &lt;td id='88'>hello&lt;/td>
      &lt;td id='77'>hello2&lt;/td>
      &lt;td id='66'>hello3&lt;/td>
      &lt;td id='55'>hello4&lt;/td>
    &lt;/tr>
  &lt;/tbody>
&lt;/table>
</pre>
<p>This was just another of those &#8220;external brain dump&#8221; posts&#8230;I didn&#8217;t want to loose my memory and there are a few subtle points (or at least a few things that I found out by trial-and-error). There&#8217;s not too much <a href="http://groovy.codehaus.org/Creating+XML+using+Groovy's+MarkupBuilder">other</a> stuff around.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/02/03/markupbuilder-how-do-i-love-thee/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solving the Enterprise Integration Puzzle with Spring Integration</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 12:28:45 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=652</guid>
		<description><![CDATA[Back in May 2009, I mentioned that I had an article published in GroovyMag.
GroovyMag is very nice in that it allows the author to republish their work after a &#8216;decent&#8217; interval has passed (either 60 or 90 days, can&#8217;t quite remember at the moment). That period is well and truly passed for this article so [...]]]></description>
			<content:encoded><![CDATA[<p>Back in May 2009, I <a href="/wordpress/2009/05/05/groovymag-may-issuenow-with-added-bob-brown/">mentioned</a> that I had an article published in <a href="http://groovymag.com/">GroovyMag</a>.</p>
<p>GroovyMag is very nice in that it allows the author to republish their work after a &#8216;decent&#8217; interval has passed (either 60 or 90 days, can&#8217;t quite remember at the moment). That period is well and truly passed for this article so here it is in its full resplendency. Enjoy!</p>
<p><em>[edit]</em><br />
Forgot to <a href='http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/exemplar-2009.apr.15.zip'>make the source available</a> when I first republished this article. Silly me. All fixed now!</p>
<hr />
<img src="/wordpress/wp-content/uploads/2009/05/gm7_400.jpg" alt="gm7_400" title="gm7_400" width="400" height="517" class="alignnone size-full wp-image-334" /></p>
<p><strong>Solving the Enterprise Integration Puzzle<br />
Getting Started with Spring Integration</strong></p>
<p>Groovy is frequently promoted as &#8220;the scripting language for the JVM.&#8221; Grails is often described as being &#8220;great for smaller, quick-to-build web applications.&#8221; Neither of these pieces of perceived wisdom really gives the Groovy/Grails combination its due: a powerful tool in the Systems Integrator&#8217;s armory. This article will show how Groovy and Grails&#8211;in conjunction with SpringSource&#8217;s up-and-coming &#8220;Spring Integration&#8221; project&#8211;can make complex systems integration tasks as easy as building a standalone web application.</p>
<h1>A Brief Overview of Spring Integration</h1>
<p>Systems integration is frequently likened to attempting to piece together a badly made jigsaw puzzle. The end goal is often quite fuzzy; there may be several potential solutions to consider; there may be many conflicting approaches to evaluate; and when all is said and done, sometimes all that can be done is to say &#8220;To heck with the Grand Plan!&#8221; and &#8216;adapt&#8217; the puzzle using a pair of nice sharp scissors.</p>
<p>Spring Integration (SI) is a recent project within the Spring stable that provides numerous tools to make the systems integration task less frustrating. SI builds on several existing Spring stablemates, but provides a unified way of configuring these components and linking them together. According to SI, all message endpoints (which act with and on behalf of application components) interact via messages sent over various flavors of messaging channels, perhaps undergoing various transformations along the way. In addition, external resources (files, JMS-based queueing systems, SOAP-based WebServices, etc.)  interact with these channels via simple-to-configure adapters.</p>
<p>SI imposes very little onto the developer; almost everything in the system can be implemented using simple POG/JOs (Plain Old Groovy/Java Objects) and configuration is typically via XML or Annotations.</p>
<p>SI provides out-of-the-box support for many of the patterns defined in Hohpe and Woolfe&#8217;s <em>Enterprise Integration Patterns</em> book and associated website and&#8211;as this article will show&#8211;is quite &#8220;Groovy friendly.&#8221;</p>
<h1>A Small Example Application</h1>
<p>In this article, I am going to take a very simple systems integration task and build a small example application. The application is a small Grails application that performs a simple function: given a customer number, it calculates the shipping cost for a single widget.</p>
<p>To show how Spring Integration can be used, I am assuming that a customer will enter their customer ID into a Grails-originated web page, which is then routed to one instance of a set of JMS servers. The associated address data is then retrieved, the city field extracted and then passed on to a SOAP-based WebService that calculates the cost of shipping widgets from Brisbane to the customer&#8217;s home city. To add a smidgen of realism, I have built the various services to be completely unrelated; in particular, they do not reference any form of standardized messaging schema. The integration pipeline needs to handle various simple message types, including strings, CSV-formatted data records, XML-formatted strings and floats.</p>
<p>Figure 1 provides a high-level view of the application.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/gm_si_image001.jpg" alt="gm_si_image001" title="gm_si_image001" width="665" height="289" class="alignnone size-full wp-image-667" /></p>
<p>Figure 1: The processing flow and major components comprising the example application</p>
<p>The various steps highlighted in this flow are:</p>
<ol>
<li>The customer ID (a simple string) is entered into the Grails web application and passed off to a generic SI gateway. The gateway places the customer ID on an internal channel that leads to a message router.</li>
<li>The router retrieves the message from its inbound channel and determines which available channel to use to ensure that the message is handled by the appropriate JMS server instance.</li>
<li>The message is then handled by a SI JMS &#8220;channel adapter,&#8221; which deals with the mechanics of working with the underlying external JMS server.</li>
<li>The nominated JMS server instance produces a record (a CSV-formatted string) that is placed onto a shared reply channel.</li>
<li>The CSV record is removed from the shared channel and transformed. The result of the transformation is an XML-formatted string which is again placed on a ‘downstream&#8217; queue.</li>
<li>The WebService channel adaptor removes the string from its request channel and invokes the external SOAP WebService for further processing.</li>
<li>The WebService response (a single float) is then passed back to the originating messaging gateway, which returns it to the Grails controller.</li>
</ol>
<p>This is a very simple system and it may seem that this is overkill. There is a payoff, however: SI makes it easy to plug in disparate (often legacy) systems and thus produces an expandable framework that is capable of being built out to cover future, more complex, situations.</p>
<h2>The Pieces of the Jigsaw Puzzle</h2>
<p>Before starting out on the integration exercise proper, it is worth taking a quick look at the various pieces of the jigsaw puzzle that are going to be joined together.</p>
<p>You will quickly see that all the pieces are exceptionally simplistic. I haven&#8217;t even tried to make them correspond to a multitude of real-life issues such as error handling, logging, configuration, etc., which have been almost completely ignored. This is by design: for the purposes of this article, I want to focus mostly on SI, not on the various services.</p>
<h2>The Grails Web Application</h2>
<p>Figure 2 shows the Grails web interface &#8220;in action.&#8221; It is very simple, with only a single form and a single results page.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/gm_si_image002.jpg" alt="gm_si_image002" title="gm_si_image002" width="665" height="246" class="alignnone size-full wp-image-670" /></p>
<p>Figure 2: The deployed Grails web application</p>
<p>The ‘meat&#8217; of the application (as far as this article is concerned) lies in the single Grails controller class shown in Listing 1.</p>
<pre>
public class SpringIntegrationController {

  def siGateway

  def index = { }

  def submit = {
    long start = System.currentTimeMillis()
    def msg = params.custid
    siGateway.send(msg)
    def got = siGateway.receive()
    flash.message =
      "Query took: ${System.currentTimeMillis() - start} millis."
    [shippingCost: got]
    }
  }
</pre>
<p>Listing 1: The Grails controller class</p>
<p>There are two points of interest in this simple class.</p>
<p>The siGateway instance injected from the Spring application context constitutes the sole point of contact between the Grails web application and the SI framework. (In theory, SI allows for an even less intrusive interface than this, based around dynamically constructed proxies, but a bug surfaced as I started writing the application…no matter, the hard way is not too onerous to use and I am sure that the SI guys will soon squash the bug.)</p>
<p>The submit closure is responsible for handling the POSTed form data and for driving the injected siGateway instance through its paces. It is pretty straightforward: all the action is happening over in &#8220;SI-land.&#8221;</p>
<h2>The JMS Application</h2>
<p>For the example application, I have written a very simple JMS service (using Apache ActiveMQ as the messaging provider), as shown in Listing 2.</p>
<pre>
import javax.jms.Session
import org.apache.activemq.ActiveMQConnectionFactory

public class AMQService
{
  private static factory =
	  new ActiveMQConnectionFactory("tcp://localhost:61616")

  public static void main(String[] args) throws Exception
  {
    def cKey = args[0]
    def cFile = args[1]

    println 'Starting...'
    println "Config key: $cKey"
    println "Config file: $cFile"

    def config =
      new ConfigSlurper(cKey).parse(new File(cFile).toURL())

    def database = config.database
    println "Database: $database"

    def inQ = config.inQ
    println "Incoming Queue: $inQ"

    def replyTopic = config.replyTopic
    println "Reply Topic: $replyTopic"

    def qConn = factory.createQueueConnection()
    def qSession =
      qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE)
    def consumer =
      qSession.createConsumer(qSession.createQueue(inQ))

    def tConn = factory.createTopicConnection()
    def tSession =
      qConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE)
    def producer =
      tSession.createProducer(tSession.createTopic(replyTopic))

    qConn.start()
    tConn.start()

    for ( ; ; )
      process(database,
              tSession.createTextMessage(),
              consumer,
              producer)
  }

  private static process(database, replyMessage, consumer, producer)
  {
    try
    {
      def textMessage = consumer.receive()  // indefinite blocking
      replyMessage.with {
        setText(getResponse(database, textMessage.getText()))
        setJMSCorrelationID(textMessage.getJMSCorrelationID())
      }
      producer.send(replyMessage)
    }
    catch (Throwable t)
    {
      t.printStackTrace()
    }
  }

  private static getResponse(database, inMsg)
  {
    def resp = database[inMsg]
    println "Request: '$inMsg'; Response: '$resp'"
    resp
  }
}
</pre>
<p>Listing 2: The JMS server</p>
<p>This is a standard JMS service; no need to elaborate.</p>
<p>One point to note (that is not directly SI-related, but of interest nonetheless) is that the service is written to allow multiple instances to run at the same time, dealing with a partitioned data space. For the purposes of the example application, I have configured two instances. One instance is prepared to deal with customer IDs whose first character is in the range a-l and the second will deal with the rest of the alphabet.</p>
<p>The service accepts input via a uniquely-designated input queue, but sends its response to a shared topic. This structure simplifies things by ensuring that any downstream component merely has to handle a single publish/subscribe channel (which can carry data from multiple sources), rather than trying to deal with a multitude of point-to-point links.</p>
<p>Each server instance is driven by a pair of application parameters, defining:</p>
<ul>
<li>The location of the configuration file to use</li>
<li>The appropriate environment section in the designated configuration file</li>
</ul>
<p>The configuration file supplies:</p>
<ul>
<li>The name of the input queue to use</li>
<li>The name of the output topic to receive the responses</li>
<li>The actual static database to use (I did warn that these applications were extremely simple!)</li>
</ul>
<p>The service makes use of ConfigSlurper&#8217;s ability to deal with different environment sections and so I can define a single configuration file (see Listing 3) to configure the different instances uniquely.</p>
<pre>
replyTopic="SI.REPLY.TOPIC"

replyTopic="SI.REPLY.TOPIC"

environments {
  al {
    inQ="SI.AL.REQUEST"
    database=['b9876':'123 Nowhere St,Brisbane',
              'f0234':'42 Imaginary Place,Darwin']
    }
  mz {
    inQ="SI.MZ.REQUEST"
    database=['x5555':'123 Fake St,Hobart',
              'w8888':'000 Talkfest Lane,Canberra']
    }
  }
</pre>
<p>Listing 3: JMS server configuration file</p>
<p>This service accepts a string, but returns a CSV-formatted record.</p>
<h2>The WebService</h2>
<p>The final part in the jigsaw puzzle is a SOAP WebService built on top of the facilities provided by GroovyWS.</p>
<p>The service&#8217;s raison-d&#8217;être is to retrieve the cost of shipping <em>n</em> widgets between major cities in Australia; see Listing 4 and Listing 5.</p>
<pre>
public class ShippingCostWebService {

  static costs = [
    Brisbane: [ Brisbane:0.0F,
                Darwin:44.44F,
                Canberra:22.22F,
                Hobart:88.88F ],
    Darwin: [ Brisbane:44.44F,
              Darwin:0.0F,
              Canberra: 33.33F,
              Hobart: 99.99F ],
    Canberra: [ Brisbane:22.22F,
                Darwin:33.33F,
                Canberra: 0.0F,
                Hobart: 77.77F ],
    Hobart: [ Brisbane:88.88F,
              Darwin:99.99F,
              Canberra: 77.77F,
              Hobart: 0.0F ],
  ]

  Float calculateShippingCost(String fromLoc,
                              String toLoc,
                              Integer nItem) {
    def cost = costs[fromLoc][toLoc] * nItem
    println "calculateShippingCost($fromLoc,$toLoc,$nItem) => $cost"
    cost
    }
}
</pre>
<p>Listing 4: The shipping cost WebService</p>
<pre>
println 'Starting...'

def ws = new groovyx.net.ws.WSServer()

ws.setNode("ShippingCostWebService",
           "http://localhost:6980/ShippingCostWebService")

ws.start()

println '...Started.'
</pre>
<p>Listing 5: The GroovyWS WebService server harness</p>
<p>I can&#8217;t lie! This is just an old WebService that I had lying around that I created for a conference presentation, and which I have adopted for this application. It doesn&#8217;t have a customized API and isn&#8217;t necessarily a perfect fit to the task. In the systems integration world, improvisation is often required to squeeze data out of the numerous ‘sub-optimal&#8217; nooks and crannies that are found all over an enterprise.</p>
<h1>Joining the Pieces Together</h1>
<p>Now that you are familiar with the basic componentry, it is time to look at SI proper.</p>
<p>As with any Spring project, SI is configured separately to the actual code in an application. Since this application is based on Grails, I have chosen to use the nice resources.groovy Grails Spring Beans DSL configuration file, rather than the ‘traditional&#8217; XML-based configuration.</p>
<p>Listing 6 shows the complete configuration.</p>
<pre>
beans = {
  xmlns si:"http://www.springframework.org/schema/integration"
  xmlns jms:"http://www.springframework.org/schema/integration/jms"
  xmlns stream:"http://www.springframework.org/schema/integration/stream"
  xmlns ws:"http://www.springframework.org/schema/integration/ws"

  // SI componentry and plumbing
  si {
    poller(default: true) {
      "interval-trigger"(interval: 1, "time-unit": "SECONDS")
    }
    router("input-channel": "routerChannel",
           ref: "highLowRouter",
           method: "route")
    transformer("input-channel": "InboundTopic",
                "output-channel": "TransformedInbound",
                ref: "csvStringTransformer",
                method: "transform")
    channel(id: "routerChannel")
    channel(id: "ALOutboundChannel")
    channel(id: "MZOutboundChannel")
    channel(id: "RoutingRejectChannel") {
      queue(capacity: "256")
    }
    channel(id: "TransformedInbound") {
      queue(capacity: "16")
    }
    channel(id: "InboundTopic") {
      queue(capacity: "16")
    }
    channel(id: "ShippingCostChannel",
            dataType: "java.lang.Float") {
      queue(capacity: "16")
    }
  }

  stream {
    "stderr-channel-adapter"(channel:"errorChannel",
                             "append-newline": true)
  }

  // WebService stuff
  ws {
    "outbound-gateway"("request-channel": "TransformedInbound",
                       "reply-channel": "ShippingCostChannel",
                        uri: "http://localhost:6980/ShippingCostWebService")
  }

  // AMQ/JMS stuff
  connectionFactory(org.apache.activemq.pool.PooledConnectionFactory) { bean ->
    bean.destroyMethod = "stop"
    connectionFactory = { org.apache.activemq.ActiveMQConnectionFactory cf ->
      brokerURL = "tcp://localhost:61616"
    }
  }

  "AL.REQUEST"(org.apache.activemq.command.ActiveMQQueue, "SI.AL.REQUEST")
  "MZ.REQUEST"(org.apache.activemq.command.ActiveMQQueue, "SI.MZ.REQUEST")
  "REPLY"(org.apache.activemq.command.ActiveMQTopic, "SI.REPLY.TOPIC")

  jms {
    "outbound-channel-adapter"(channel: "ALOutboundChannel",
                               destination: "AL.REQUEST")

    "outbound-channel-adapter"(channel: "MZOutboundChannel",
                               destination: "MZ.REQUEST")

    "message-driven-channel-adapter"(channel: "InboundTopic",
                                     destination: "REPLY")
   }

  // general componentry
  siGateway(org.springframework.integration.gateway.SimpleMessagingGateway) {
    requestChannel = ref("routerChannel")
    replyChannel = ref("ShippingCostChannel")
    replyTimeout = "10000"
  }

  highLowRouter(au.com.transentia.si.LookupRouter)

  csvStringTransformer(au.com.transentia.si.CsvTransformer) {
    homeBase = 'Brisbane'
  }
}
</pre>
<p>Listing 6: The Spring Integration configuration</p>
<p>As you read the following discussion, you may find it useful to refer back to Figure 1.</p>
<p>The configuration is structured into various sections, according to the needs of SI and of the various resources that are being integrated.</p>
<p>The si section (more precisely, those elements of SI configured via the XML namespace allocated the si prefix in this document) configures the various aspects of SI itself. This includes establishing the various channels that interlink the components, defining a few application-specific components (such as the router and transformer), and putting in place a default polling schedule for those parts of SI that need to poll.</p>
<p>It is worth examining the router and transformer components here. I have mentioned that the JMS services deal with a partitioned data space and that traffic is directed to an individual service based on the actual data message being processed. SI allows for the definition of an application-specific router to perform this type of task, in this case the method route of the highLowRouter instance. Listing 7 shows the code for the router.</p>
<pre>
package au.com.transentia.si

public class LookupRouter {

  public String route(String msg) {
    switch(msg) {
      case ~/(?i:[a-l].*)/: return 'ALOutboundChannel'
      case ~/(?i:[m-z].*)/: return 'MZOutboundChannel'
      default: return 'reject'
    }
  }
}
</pre>
<p>Listing 7: The router class</p>
<p>The router examines the incoming message data and determines the appropriate outbound path for the message. Groovy&#8217;s wonderfully versatile switch statement, combined with the ability to do case-independent pattern matching, makes for beautifully minimalistic code.</p>
<p>The transformer is equally simple, as Listing 8 shows.</p>
<pre>
package au.com.transentia.si

public class CsvTransformer {
  def homeBase

  public String transform(String csv) {
    def dest = csv.tokenize(',')[1]

    """<def :calculateShippingCost xmlns:def="http://DefaultNamespace">
         </def><def :arg0>$homeBase</def>
         <def :arg1>$dest</def>
         <def :arg2>1</def>
      """
  }
}
</pre>
<p>Listing 8: The transformer class</p>
<p>This code is presented with an input CSV-formatted record, extracts the relevant field, and passes an XML-formatted string onwards.</p>
<p>Recall that the WebService&#8217;s API is not custom-built for the purpose of this application; for this use, arg2 (the nItems parameter) is always fixed at 1.</p>
<p>The stream section of the configuration merely allocates a generic channel listener so that the standard errorChannel is not silently ignored; this configuration will ensure that errors/exceptions, etc., are logged.</p>
<p>The ws section deals&#8211;unsurprisingly&#8211;with WebService integration. The section configures an SI outbound gateway that is capable of receiving a request on a specified channel, invoking the configured WebService and finally sending the result to the appropriate response channel. All this is specified declaratively: the actual mechanism of dealing with the WebService (retrieving WSDL documents, generating proxies and handling XML-based request/response messages) is completely hidden away.</p>
<p>The remaining configuration concerns SI&#8217;s JMS adapter and ActiveMQ integration.</p>
<p>The siGateway has been discussed previously.</p>
<p>By default, all SI&#8217;s JMS adapters reference a bean with the standard name of connectionFactory. It is the responsibility of this bean to ‘vend&#8217; connections to the external JMS system. In this case, a connection pool to a local Apache ActiveMQ server running at the URL &#8220;tcp://localhost:61616&#8243; is being created. Since the external connections are pooled for efficiency, by specifying destroyMethod=&#8217;stop&#8217; we ensure that they are simply inactivated after each (re)use and are never actually discarded.</p>
<p>Note: I found the actual syntax used to declare the connectionFactory a little tricky. I had to ask for help on the excellent user@grails.codehaus.org mailing list to get it right! Thanks to the generous souls who pointed me in the right direction.</p>
<p>Following the definition of the the connectionFactory, we create two instances of ActiveMQ queues and an instance of an ActiveMQ topic. It is these that carry the messages to/from the external JMS resources.</p>
<p>The jms section configures two JMS-specific outbound channel adapters and one inbound channel adapter. As the names suggest, these are concerned with driving (or being driven by) the ActiveMQ instances declared above. The configured message-driven-channel-adapter instance defines a component that will be asynchronously &#8220;actively invoked&#8221; to handle an incoming message. It is possible to configure a polling-oriented component, but this is generally less flexible, and may waste CPU, and increase the latency in the system.</p>
<p>As with the WebService gateway, everything is declarative.</p>
<h1>Admiring the Finished Puzzle</h1>
<p>SI has enabled a deceptively simple solution to a fairly complex problem. There are no messy tracts of confusing mechanistic code; the system is essentially defined all in a single configuration; the individual components are simple and (generally) reusable; and the groundwork for coping with change set with very little effort.</p>
<p>SI is a simple but powerful toolkit; the example application I have discussed here has really just touched the surface of what is possible. SI provides much more, including facilities for secure channels, inbound/outbound mail handling, event handling, RMI integration and much better XML handling than I have touched upon here.</p>
<p>Remember that these are still early days for SI: for example, there are no debuggers or GUI editors as found in the big &#8220;name brand&#8221; systems integration tools. In time these tools may come but for now remember that SI is orders of magnitude simpler, and the SI/Groovy/Grails triumvirate makes the developer many times more productive than some other tools I have used.</p>
<p>I hope that I have stimulated your interest in SI and shown that a Grails application need not be limited to serving up &#8220;little web apps&#8221; but can actually service the needs of larger-scale systems integration tasks.</p>
<p>I hope that I have also been able to show that when the time comes to get out the scissors, Groovy is more than equal to the task of &#8220;slicing and dicing&#8221; until the pieces of the systems integration jigsaw puzzle fit nicely together.</p>
<h1>Learn More</h1>
<ul>
<li>Gregor Hohpe and Bobby Woolf, <em>Enterprise</em><em> Integration Patterns : Designing, Building, and Deploying Messaging Solutions (ISBN 0321200683)</em>, also <a href="http://www.enterpriseintegrationpatterns.com/">http://www.enterpriseintegrationpatterns.com/</a></li>
<li>Spring Integration Home, <a href="http://www.springsource.org/spring-integration">http://www.springsource.org/spring-integration</a></li>
<li>Apche ActiveMQ, <a href="http://activemq.apache.org/">http://activemq.apache.org</a></li>
<li>GroovyWS, <a href="http://docs.codehaus.org/display/GROOVY/GroovyWS">http://docs.codehaus.org/display/GROOVY/GroovyWS</a>. The exemplar application uses the 0.5 snapshot jars from <a href="http://snapshots.dist.codehaus.org/groovy/distributions/groovyws/">http://snapshots.dist.codehaus.org/groovy/distributions/groovyws/</a></li>
</ul>
<p><em>Bob Brown is the director and owner of Transentia Pty. Ltd.. Based in beautiful Brisbane, Australia, Bob is a specialist in Enterprise Java and has found his niche identifying and applying leading-edge technologies and techniques to customers problems.</em></p>
<hr />
Watch out for my other Groovymag articles&#8230;coming soon to a browser near you.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Brisbane is &#8220;Groovy, Baby!&#8221;</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/09/29/brisbane-is-groovy-baby/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/09/29/brisbane-is-groovy-baby/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 02:27:46 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=502</guid>
		<description><![CDATA[I was at yesterday&#8217;s Groovy/Grails Queensland meetup.
We started talking about the wealth of talent and Groovy/Grails &#8216;names&#8217; that were clustered in and around Beautiful Brisbane, Australia. People with major, direct influence on the various Gr8 technologies. People like: Dr. Paul King, Lee Butts, Luke Daley, Bradley Beddoes (to name but a few). All movers and [...]]]></description>
			<content:encoded><![CDATA[<p>I was at yesterday&#8217;s <a href="http://www.meetup.com/groovygrailsqld/">Groovy/Grails Queensland</a> meetup.</p>
<p>We started talking about the wealth of talent and Groovy/Grails &#8216;names&#8217; that were clustered in and around Beautiful <a href="http://www.ourbrisbane.com/">Brisbane</a>, Australia. People with major, direct influence on the various Gr8 technologies. People like: <a href="http://www.asert.com.au/">Dr. Paul King</a>, <a href="http://www.meetup.com/groovygrailsqld/members/8098591/">Lee Butts</a>, <a href="http://stuff.ldaley.com/">Luke Daley</a>, <a href="http://intient.com/">Bradley Beddoes</a> (to name but a few). All movers and shakers in the Gr8 world. Many were in the room at the time.</p>
<p><a href="http://refactor.com.au/blogs/steve-dalton">Steve Dalton</a> is <a href="http://cybershovel.com/doku.php?id=groovymagarticle">maintaining a slightly bigger list</a>.</p>
<p>We truly have a world-class, leading-edge group here.</p>
<p>To quote Lee: &#8220;We are the Australian HUB for Grails/Groovy :)&#8221;</p>
<p>(I&#8217;m so glad that I managed to avoid using the phrase &#8216;paradigm shifting&#8217;&#8230;but it was hard ;-))</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/09/29/brisbane-is-groovy-baby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
