<?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>Ola Bildtsen</title>
	<atom:link href="http://bildtsen.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://bildtsen.com</link>
	<description>Flex, Groovy/Grails, and other neat stuff</description>
	<lastBuildDate>Fri, 20 Nov 2009 19:40:37 +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>Stark Security version 0.4.3 released</title>
		<link>http://bildtsen.com/2009/11/stark-security-version-0-4-3-released/</link>
		<comments>http://bildtsen.com/2009/11/stark-security-version-0-4-3-released/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 19:39:59 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=179</guid>
		<description><![CDATA[I&#8217;m pleased to announce the latest version of the Stark Security plugin for Grails has been released.  Docs have been updated and release notes are available: http://grails.org/plugin/stark-security.
In short, this release upgrades to Spring Security 2.0.5, and contains a fix for configurable support for session fixation attack prevention.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to announce the latest version of the Stark Security plugin for Grails has been released.  Docs have been updated and release notes are available: <a href="http://grails.org/plugin/stark-security">http://grails.org/plugin/stark-security</a>.</p>
<p>In short, this release upgrades to Spring Security 2.0.5, and contains a fix for configurable support for session fixation attack prevention.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2009/11/stark-security-version-0-4-3-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webcast: Introduction to Flex and AIR</title>
		<link>http://bildtsen.com/2009/10/webcast-introduction-to-flex-and-air/</link>
		<comments>http://bildtsen.com/2009/10/webcast-introduction-to-flex-and-air/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 17:29:08 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=158</guid>
		<description><![CDATA[I recently did a &#8220;tech talk&#8221; at work &#8212; an introduction to Adobe&#8217;s Flex and AIR.  The presentation is geared to the techie with some UI-building experience but with little or no knowledge of Flex or FlexBuilder.
Although there are some high-level introductory/overview slides up front, the bulk of the presentation is a build-it-from-scratch session [...]]]></description>
			<content:encoded><![CDATA[<p>I recently did a &#8220;tech talk&#8221; at work &#8212; <a href="http://bildtsen.com/wp-content/uploads/2009/10/FlexIntroPresentationLarge.mov">an introduction to Adobe&#8217;s Flex and AIR</a>.  The presentation is geared to the techie with some UI-building experience but with little or no knowledge of Flex or FlexBuilder.</p>
<p>Although there are some high-level introductory/overview slides up front, the bulk of the presentation is a build-it-from-scratch session that shows how to use FlexBuilder to put together a simple Flex app (the obligatory Twitter client).  It also shows how to work with a library project, and then goes on to create an AIR application using a shared component.  Towards the end, I&#8217;m firing up FlexMonkey to show how to test the Flex app we built and how to generate the scripts and AS3 code needed to integrate those tests in a CI build.</p>
<p>The slides are <a href='http://bildtsen.com/wp-content/uploads/2009/10/FlexIntroSlides.pdf'>here</a>.  There are not that many, but there are some useful links on the last slide.</p>
<p>The Flex projects built during the presentation are <a href='http://bildtsen.com/wp-content/uploads/2009/10/FlexAirDemo.tar.gz'>here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2009/10/webcast-introduction-to-flex-and-air/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://bildtsen.com/wp-content/uploads/2009/10/FlexIntroPresentationLarge.mov" length="281253296" type="video/quicktime" />
		</item>
		<item>
		<title>Stark Security version 0.4.2 released</title>
		<link>http://bildtsen.com/2009/01/stark-security-version-042-released/</link>
		<comments>http://bildtsen.com/2009/01/stark-security-version-042-released/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 17:08:11 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=155</guid>
		<description><![CDATA[Readers of this blog and people on the grails user list noted some difficulties with UTF encoding with the previous release of the stark security plugin.  I&#8217;m happy to announce this bug-fix release (version 0.4.2) which takes care of the UTF encoding problem, and also fixes another defect related to moving the User and Role [...]]]></description>
			<content:encoded><![CDATA[<p>Readers of this blog and people on the grails user list noted some difficulties with UTF encoding with the previous release of the stark security plugin.  I&#8217;m happy to announce this bug-fix release (version 0.4.2) which takes care of the UTF encoding problem, and also fixes another defect related to moving the User and Role domain classes into packages.</p>
<p>Please give it a whirl and let me know if you have any comments and/or questions!</p>
<p>Docs and release notes are here: http://www.grails.org/Stark+Security+Plugin</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2009/01/stark-security-version-042-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Stark Security Version 0.4 Released</title>
		<link>http://bildtsen.com/2009/01/stark-security-version-04-released/</link>
		<comments>http://bildtsen.com/2009/01/stark-security-version-04-released/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 17:33:52 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=151</guid>
		<description><![CDATA[This is the second release since my last post &#8212; since 0.2.x these are the highlight changes:

allow for simple listening/handling of Spring Security authentication/authorization events
allow the application to participate/intercept at various points of the Spring Security filter chain.
various defect fixes

Updated docs and release details are available here: http://www.grails.org/Stark+Security+Plugin
]]></description>
			<content:encoded><![CDATA[<p>This is the second release since my last post &#8212; since 0.2.x these are the highlight changes:</p>
<ul>
<li>allow for simple listening/handling of Spring Security authentication/authorization events</li>
<li>allow the application to participate/intercept at various points of the Spring Security filter chain.</li>
<li>various defect fixes</li>
</ul>
<p>Updated docs and release details are available here: <a href="http://www.grails.org/Stark+Security+Plugin" target="_blank">http://www.grails.org/Stark+Security+Plugin</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2009/01/stark-security-version-04-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Stark Security Plugin version 0.2.2 Released</title>
		<link>http://bildtsen.com/2008/12/stark-security-plugin-version-02-released/</link>
		<comments>http://bildtsen.com/2008/12/stark-security-plugin-version-02-released/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 16:49:54 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=146</guid>
		<description><![CDATA[I&#8217;m pleased to announce the release of version 0.2 of the Stark Security plugin.  Not a huge deal, but a few convenience enhancements:

Enable arbitrary password encoding algorithms, on a DAO provider basis
Allow for tweaks to authorization mappings in StarkSecurityConfig.groovy without app restart.
Let user install the plugin but defer configuration (this used to result in [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to announce the release of version 0.2 of the Stark Security plugin.  Not a huge deal, but a few convenience enhancements:</p>
<ul>
<li>Enable arbitrary password encoding algorithms, on a DAO provider basis</li>
<li>Allow for tweaks to authorization mappings in StarkSecurityConfig.groovy without app restart.</li>
<li>Let user install the plugin but defer configuration (this used to result in exceptions on app startup).</li>
</ul>
<p>The 0.2.2 bug-fix release solves an issue with custom url mappings not responding to the authorization mappings in controllers.  With this fix, any custom mappings in UrlMappings will resolve to the authorization mappings of the eventual controller target.</p>
<p>Documentation (including upgrade instructions, release notes, etc.) is here: <a href="http://www.grails.org/Stark+Security+Plugin">http://www.grails.org/Stark+Security+Plugin</a></p>
<p>As always, comments/questions/suggestions are much appreciated!</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/12/stark-security-plugin-version-02-released/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Announcing Stark Security Plugin for Grails</title>
		<link>http://bildtsen.com/2008/11/announcing-stark-security-plugin-for-grails/</link>
		<comments>http://bildtsen.com/2008/11/announcing-stark-security-plugin-for-grails/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 22:33:21 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=142</guid>
		<description><![CDATA[I&#8217;m happy to announce the release of the new Stark Security plugin to the Grails plugins repository.  It&#8217;s a cleaned-up (and, hopefully, simplified) edition of the alternative Spring Security plugin previously mentioned here.  The main focus of this plugin is to provide a simple yet strong security solution, and it&#8217;s different from the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m happy to announce the release of the new Stark Security plugin to the Grails plugins repository.  It&#8217;s a cleaned-up (and, hopefully, simplified) edition of the alternative Spring Security plugin <a href="http://bildtsen.com/?p=122">previously mentioned here</a>.  The main focus of this plugin is to provide a simple yet strong security solution, and it&#8217;s different from the standard acegi and jsecurity plugins in that it offers:</p>
<ul>
<li><b>Lock-down or &#8216;pessimistic&#8217; approach.</b> Instead of leaving the web application open and relying on configured rules to lock down certain areas, the Stark Security plugin locks down everything by default. Developers open up access on a controller-method basis as they are coding the controllers.</li>
<li><b>Authorization mappings by convention.</b> The determination of which roles can access which URLs is declared by convention in every controller, right next to the eventual URL end-points (controller methods). This makes for very straight-forward implementation and maintenance of the security rules.</li>
</ul>
<p>Version 0.1 is available by simply running this from within your Grails project:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">grails install-plugin stark-security</pre></div></div>

<p>Documentation is available at the <a href="http://www.grails.org/Stark+Security+Plugin">Stark Security Plugin page</a> at the <a href="http://grails.org/Plugins#">Grails plugins web site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/11/announcing-stark-security-plugin-for-grails/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Production-Grade SpringSecurity Plugin for Grails</title>
		<link>http://bildtsen.com/2008/11/production-grade-springsecurity-plugin-for-grails/</link>
		<comments>http://bildtsen.com/2008/11/production-grade-springsecurity-plugin-for-grails/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 21:54:00 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=122</guid>
		<description><![CDATA[In my previous post &#8220;Production-Grade Acegi Security for Grails&#8220;, readers correctly commented that the underlying technology for the plugin was rather outdated.  Some of the assertions in that post were based on an early version of the standard Acegi plugin for Grails, and the underlying security library was an outdated acegi version.
To make a [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous post &#8220;<a href="http://bildtsen.com/?p=3">Production-Grade Acegi Security for Grails</a>&#8220;, readers correctly commented that the underlying technology for the plugin was rather outdated.  Some of the assertions in that post were based on an early version of the standard Acegi plugin for Grails, and the underlying security library was an outdated acegi version.</p>
<p>To make a long story short, I have since upgraded the plugin to the latest version of SpringSecurity (2.0.4 at the time of writing).  The plugin is available here as part of a demo application (just like in the previous post):</p>
<p><span id="more-122"></span></p>
<p><a href='http://bildtsen.com/?attachment_id=124' rel='attachment wp-att-124'>SpringSecurityGrailsPluginDemo.zip</a></p>
<p>Prior to doing this update, I reviewed the latest Grails plugins available for both JSecurity and Acegi (yes, it should be renamed &#8216;SpringSecurity&#8217;).  Although they are now considerably easier to configure and do provide LDAP authentication alongside simple DAO authentication, they still lack some important aspects of web application security that I was attempting to address:</p>
<ul>
<li><strong>Pessimistic authorization scheme</strong>.  Default to no access for anybody to anything, open up holes as needed.  This may not work for everybody, but my goal is to reduce the risk of leaving unintended content out there (given how easy it is to implement a Grails controller method).</li>
<li><strong>Ease of implementation</strong>.  A developer should readily be able to configure a controller method to a certain security level at the time of feature implementation.  While I believe security should be an implementation-time decision, it should NOT be an obstacle to rapid and agile development.</li>
<li><strong>Good maintainability</strong>.  When Grails controllers are re-factored or removed, it should be obvious what changes need to be made from a security perspective.   Changes in controller structure should not result in hours of tracing down security rules.</li>
</ul>
<p>To get a better understanding of how my plugin addresses those concerns, please read the <a href="http://bildtsen.com/?p=3">original post</a>.  None of the logic posted in that original article has changed, only the internals of the plugin itself to accommodate for the upgraded SpringSecurity libraries.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/11/production-grade-springsecurity-plugin-for-grails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Manipulating Views under Cairngorm using Facades</title>
		<link>http://bildtsen.com/2008/11/manipulating-views-under-cairngorm-using-facades/</link>
		<comments>http://bildtsen.com/2008/11/manipulating-views-under-cairngorm-using-facades/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 19:13:28 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=117</guid>
		<description><![CDATA[We recently re-wrote a fairly major Flex application, having an opportunity to start from scratch with lessons learned.  The previous implementation used the Cairngorm framework, but not quite in line with its intent &#8212; it was purely used to in &#8220;data commands&#8221; to retrieve data from the server.
After reviewing some of the other MVC [...]]]></description>
			<content:encoded><![CDATA[<p>We recently re-wrote a fairly major Flex application, having an opportunity to start from scratch with lessons learned.  The previous implementation used the Cairngorm framework, but not quite in line with its intent &#8212; it was purely used to in &#8220;data commands&#8221; to retrieve data from the server.</p>
<p>After reviewing some of the other MVC frameworks out there (PureMVC mostly), we decided to stick with Cairngorm but to expand its use to the full extent it was intended.  In our mind, that meant to have Cairngorm events/commands handle all user gestures (unless they were trivial, component-local gestures like re-sorting a datagrid, etc.).  This worked great, and we were pretty happy with the emerging structure of the application except for one thing: we didn&#8217;t like the ViewHelper/ViewLocator pieces.  It seemed too cumbersome and overly structured for the simple task of having a command communicate with a view.  We also didn&#8217;t like to control views from commands via the ModelLocator (as also suggested by the Cairngorm docs), as we had tried that in the earlier version and it quickly became a disastrous mess of spaghetti bindings that were incredibly hard to unravel, much less maintain.</p>
<p><span id="more-117"></span></p>
<p>To make this process simpler, we came up with a different approach: view facades.  These facades are essentially ViewHelpers, but we eliminated the ViewLocator by making the facades singletons attached directly to the view.  A sample makes this clearer.  Consider a command GetBookDetails.  We want this command to contact the server and get the details for a particular book.  During this process, the view should show a progress or &#8220;loading&#8230;&#8221; view, to be switched out for the actual book details view when the loading is complete.  That command could look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;">    <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> GetBookDetailsCommand <span style="color: #0066CC;">implements</span> ICommand <span style="color: #66cc66;">&#123;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #66cc66;">&#40;</span>event:CairngormEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">var</span> bookEvent:GetBookDetailsEvent = event as GetBookDetailsEvent;
&nbsp;
            BookViewFacade.<span style="color: #006600;">getInstance</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">showLoadingView</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
            <span style="color: #808080; font-style: italic;">// Load the book details from the server here, using a custom HTTPServiceEvent of ours...</span>
            <span style="color: #000000; font-weight: bold;">var</span> bookServiceEvent:HTTPServiceEvent = <span style="color: #000000; font-weight: bold;">new</span> HTTPServiceEvent<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'book_get'</span>, BookModelLocator.<span style="color: #006600;">getInstance</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'book'</span>, <span style="color: #ff0000;">'book'</span><span style="color: #66cc66;">&#41;</span>;
            bookServiceEvent.<span style="color: #006600;">params</span> = <span style="color: #66cc66;">&#123;</span>id: bookEvent.<span style="color: #006600;">bookId</span><span style="color: #66cc66;">&#125;</span>
            bookServiceEvent.<span style="color: #006600;">addCommandStatusListener</span><span style="color: #66cc66;">&#40;</span>onBookResult<span style="color: #66cc66;">&#41;</span>;
            bookServiceEvent.<span style="color: #006600;">dispatch</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onBookResult<span style="color: #66cc66;">&#40;</span>statusEvent:CommandStatusEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            BookViewFacade.<span style="color: #006600;">getInstance</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">showBookDetailsView</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>    
    <span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>Notice the two calls to <code>BookViewFacade</code>, controlling the visible view in our BookView component.  That component (BookView) would look something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;">. . .    
    <span style="color: #66cc66;">&lt;</span>view:BookViewFacade id=<span style="color: #ff0000;">&quot;facade&quot;</span> bookView=<span style="color: #ff0000;">&quot;{this}&quot;</span><span style="color: #66cc66;">/&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;</span>container:ViewStack id=<span style="color: #ff0000;">&quot;viewStack&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span> resizeToContent=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #66cc66;">&gt;</span>
&nbsp;
        <span style="color: #66cc66;">&lt;</span>container:HBox id=<span style="color: #ff0000;">&quot;VIEW_LOADING&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #66cc66;">&gt;</span>
            <span style="color: #66cc66;">&lt;</span>control:Label <span style="color: #0066CC;">htmlText</span>=<span style="color: #ff0000;">&quot;Loading...&quot;</span><span style="color: #66cc66;">/&gt;</span>
        <span style="color: #66cc66;">&lt;/</span>container:HBox<span style="color: #66cc66;">&gt;</span>
&nbsp;
    	<span style="color: #66cc66;">&lt;</span>container:VBox id=<span style="color: #ff0000;">&quot;VIEW_BOOK_DETAILS&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #66cc66;">&gt;</span>
            <span style="color: #66cc66;">&lt;</span>control:Label <span style="color: #0066CC;">htmlText</span>=<span style="color: #ff0000;">&quot;{MainModelLocator.getInstance().book.title}&quot;</span><span style="color: #66cc66;">/&gt;</span>
            <span style="color: #66cc66;">&lt;</span>control:Label <span style="color: #0066CC;">htmlText</span>=<span style="color: #ff0000;">&quot;{MainModelLocator.getInstance().book.title}&quot;</span><span style="color: #66cc66;">/&gt;</span>
            . . .
    <span style="color: #66cc66;">&lt;/</span>container:ViewStack<span style="color: #66cc66;">&gt;</span>
. . .</pre></div></div>

<p>Notice the declaration of the view facade <code>BookViewFacade</code>, where the view references itself.  The facade is a singleton, implemented along these lines:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;">    <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> BookViewFacade <span style="color: #66cc66;">&#123;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">var</span> bookView:BookView;
        <span style="color: #0066CC;">private</span> <span style="color: #0066CC;">static</span> <span style="color: #000000; font-weight: bold;">var</span> instance:BookViewFacade;
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> BookViewFacade<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            instance = <span style="color: #0066CC;">this</span>;    
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> <span style="color: #000000; font-weight: bold;">function</span> getInstance<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:BookViewFacade <span style="color: #66cc66;">&#123;</span>
            <span style="color: #b1b100;">return</span> instance;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> showLoadingView<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            bookView.<span style="color: #006600;">viewStack</span>.<span style="color: #006600;">selectedChild</span> = bookView.<span style="color: #006600;">VIEW_LOADING</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> showBookDetailsView<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            bookView.<span style="color: #006600;">viewStack</span>.<span style="color: #006600;">selectedChild</span> = bookView.<span style="color: #006600;">VIEW_BOOK_DETAILS</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>The view is thus abstracted from the commands, but can be readily manipulated by singleton-access to the view facade and its methods.  You can then easily work with views from within the Cairngorm framework, without the need for maintaining ViewLocators, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/11/manipulating-views-under-cairngorm-using-facades/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Flex Implementation using Modules with URLKit Deep-Linking</title>
		<link>http://bildtsen.com/2008/11/a-flex-implementation-using-modules-with-urlkit-deep-linking/</link>
		<comments>http://bildtsen.com/2008/11/a-flex-implementation-using-modules-with-urlkit-deep-linking/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 00:28:07 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=92</guid>
		<description><![CDATA[At work, we recently had an opportunity to rebuild the Flex front end to our web application.  Having started from scratch with the initial version of the application a year and a half ago (with little prior Flex experience in our staff), this &#8220;greenfield&#8221; opportunity gave us a chance to take the lessons learned [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we recently had an opportunity to rebuild the Flex front end to our web application.  Having started from scratch with the initial version of the application a year and a half ago (with little prior Flex experience in our staff), this &#8220;greenfield&#8221; opportunity gave us a chance to take the lessons learned (and new stuff available in Flex 3) and apply them to the new project.  One important change, from an architecture point-of-view, was the introduction of modules and how to make them work with deep-linking.</p>
<p><span id="more-92"></span></p>
<p>With the first version of the app, we quickly realized that a monolithic SWF soon becomes too large to load over not-so-fast internet connections.  By modularizing the app, loading of content that is not immediately needed can be deferred until later.  There is an excellent presentation/demo of what modules are and how to use them at <a href="http://blogs.adobe.com/aharui/2007/03/modules.html">Alex Harui&#8217;s blog</a>.</p>
<p>To get around the complexities of modules and <a href="http://livedocs.adobe.com/flex/3/html/help.html?content=18_Client_System_Environment_5.html">ApplicationDomains</a>, we decided to simply load all modules into the top-level ApplicationDomain.  We also wanted to handle deep-linking in a standard way across all modules.  We use URLKit to do most of this work &#8212; there&#8217;s a detailed explanation of how URLKit works <a href="http://www.insideria.com/2008/09/advanced-flex-deep-linking-wit-1.html">here</a>.  </p>
<p>We started by creating a base class that extends <a href="http://livedocs.adobe.com/flex/3/langref/mx/modules/ModuleLoader.html">ModuleLoader</a>.  It looks something like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="actionscript actionscript" style="font-family:monospace;">    <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ModuleLoaderBase <span style="color: #0066CC;">extends</span> ModuleLoader <span style="color: #66cc66;">&#123;</span>
&nbsp;
        protected <span style="color: #000000; font-weight: bold;">var</span> isReady:<span style="color: #0066CC;">Boolean</span> = <span style="color: #000000; font-weight: bold;">false</span>;
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ModuleLoaderBase<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0066CC;">super</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            applicationDomain = ApplicationDomain.<span style="color: #006600;">currentDomain</span>;
            <span style="color: #0066CC;">this</span>.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ModuleEvent.<span style="color: #006600;">READY</span>, onReady<span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        protected <span style="color: #000000; font-weight: bold;">function</span> onReady<span style="color: #66cc66;">&#40;</span>event:Event<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            isReady = <span style="color: #000000; font-weight: bold;">true</span>;
        <span style="color: #66cc66;">&#125;</span> 
&nbsp;
        <span style="color: #808080; font-style: italic;">/**
         * This function is called from ModuleBase when upon module creationComplete event.
         */</span>
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> onModuleCreationComplete<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            initializeDeepLinking<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            MainApplicationFacade.<span style="color: #006600;">getInstance</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">appEnabledQueuePop</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/**
         * This is where sub-classes can implement deeplinking using urlKit.
         */</span>
        protected <span style="color: #000000; font-weight: bold;">function</span> initializeDeepLinking<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/**
         *  Add a noCache parameter to the module URL to force the browser to reload the module.
         */</span>
        <span style="color: #0066CC;">public</span> override <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">set</span> <span style="color: #0066CC;">url</span><span style="color: #66cc66;">&#40;</span>u:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0066CC;">super</span>.<span style="color: #0066CC;">url</span> = u + <span style="color: #ff0000;">&quot;?nocache=&quot;</span> + <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">Date</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #0066CC;">time</span>.<span style="color: #0066CC;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>Notice on line 7 how we&#8217;re pointing the application domain of the module loader to the current or top-level domain.  So all modules we&#8217;re using simply load their class definitions into the top-level ApplicationDomain.  We can do this as long as we&#8217;re not concerned with unloading modules.  If that is a need, this strategy will not work and you&#8217;d have to implement a more complex solution (probably using a &#8220;shared classes&#8221; module as outlined in the presentation linked above).</p>
<p>Using this base class, we then create a new module loader class for each one of our modules.  For instance, here&#8217;s one that loads a book details module:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;"><span style="color: #66cc66;">&lt;</span>module:ModuleLoaderBase
    xmlns:<span style="color: #0066CC;">url</span>=<span style="color: #ff0000;">&quot;http://www.allurent.com/2006/urlkit&quot;</span>
    xmlns:module=<span style="color: #ff0000;">&quot;com.acme.core.module.*&quot;</span>     
    xmlns:mx=<span style="color: #ff0000;">&quot;http://www.adobe.com/2006/mxml&quot;</span><span style="color: #66cc66;">&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;</span>mx:Script<span style="color: #66cc66;">&gt;</span>
        <span style="color: #66cc66;">&lt;!</span><span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>
&nbsp;
            <span style="color: #0066CC;">import</span> com.<span style="color: #006600;">acme</span>.<span style="color: #006600;">module</span>.<span style="color: #006600;">IBookDetailsModule</span>;
            <span style="color: #0066CC;">import</span> mx.<span style="color: #006600;">binding</span>.<span style="color: #006600;">utils</span>.<span style="color: #006600;">BindingUtils</span>;
&nbsp;
            <span style="color: #66cc66;">&#91;</span>Bindable<span style="color: #66cc66;">&#93;</span> <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">var</span> bookId:<span style="color: #0066CC;">String</span>;
            <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> module:IBookDetailsModule;
&nbsp;
            protected override <span style="color: #000000; font-weight: bold;">function</span> initializeDeepLinking<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>: <span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
                module = <span style="color: #0066CC;">this</span>.<span style="color: #006600;">child</span> as IBookDetailsModule;
                mx.<span style="color: #006600;">binding</span>.<span style="color: #006600;">utils</span>.<span style="color: #006600;">BindingUtils</span>.<span style="color: #006600;">bindProperty</span><span style="color: #66cc66;">&#40;</span>module, <span style="color: #ff0000;">&quot;bookId&quot;</span>, <span style="color: #0066CC;">this</span>,  <span style="color: #ff0000;">&quot;bookId&quot;</span><span style="color: #66cc66;">&#41;</span>;
                mx.<span style="color: #006600;">binding</span>.<span style="color: #006600;">utils</span>.<span style="color: #006600;">BindingUtils</span>.<span style="color: #006600;">bindProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">this</span>, <span style="color: #ff0000;">&quot;bookId&quot;</span>, module,  <span style="color: #ff0000;">&quot;bookId&quot;</span><span style="color: #66cc66;">&#41;</span>;
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
&nbsp;
        <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&gt;</span>
    <span style="color: #66cc66;">&lt;/</span>mx:Script<span style="color: #66cc66;">&gt;</span>
&nbsp;
&nbsp;
&nbsp;
    <span style="color: #66cc66;">&lt;</span>url:UrlRuleSet id=<span style="color: #ff0000;">&quot;urls&quot;</span><span style="color: #66cc66;">&gt;</span>
        <span style="color: #66cc66;">&lt;</span>url:UrlValueRule id=<span style="color: #ff0000;">&quot;valueRule&quot;</span> urlFormat=<span style="color: #ff0000;">&quot;/*&quot;</span> sourceValue=<span style="color: #ff0000;">&quot;bookId&quot;</span><span style="color: #66cc66;">/&gt;</span>
    <span style="color: #66cc66;">&lt;/</span><span style="color: #0066CC;">url</span>:UrlRuleSet<span style="color: #66cc66;">&gt;</span>      
&nbsp;
<span style="color: #66cc66;">&lt;/</span>module:ModuleLoaderBase<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Notice the use of an interface (IBookDetailsInterface) to get a handle on the loaded module.  This enables us to &#8220;talk&#8221; to the module without compiling it into the main application (the entire reason for going with modules in the first place).  Also note the two-way binding of the bookId property into and out of the module.  This enables us to set the bookId property on the module loader <b>or</b> the module, and the change will be reflected either way in the browser nav bar.</p>
<p>So now on to the actual module.  First, we have a base class that all modules extend from:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;">    <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ModuleBase <span style="color: #0066CC;">extends</span> Module <span style="color: #66cc66;">&#123;</span>
&nbsp;
        <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ModuleBase<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0066CC;">super</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
            <span style="color: #0066CC;">this</span>.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>FlexEvent.<span style="color: #006600;">CREATION_COMPLETE</span>, onCreationComplete<span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onCreationComplete<span style="color: #66cc66;">&#40;</span>event:Event<span style="color: #66cc66;">&#41;</span>: <span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">var</span> loader:ModuleLoaderBase = ModuleLoaderBase<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">this</span>.<span style="color: #006600;">parent</span><span style="color: #66cc66;">&#41;</span>;
            loader.<span style="color: #006600;">onModuleCreationComplete</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>Really, the sole purpose of this base class is to call the onModuleCreationComplete function on the module loader base class.  This so that our urlKit properties can be created at the appropriate time.</p>
<p>The sample BookDetailsModule then looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;"><span style="color: #66cc66;">&lt;</span>module:ModuleBase
    xmlns:mx=<span style="color: #ff0000;">&quot;http://www.adobe.com/2006/mxml&quot;</span>
    xmlns:module=<span style="color: #ff0000;">&quot;com.acme.core.module.*&quot;</span>
    <span style="color: #0066CC;">implements</span>=<span style="color: #ff0000;">&quot;com.acme.module.IBookDetailsModule&quot;</span><span style="color: #66cc66;">&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;</span>mx:Script<span style="color: #66cc66;">&gt;</span>
        <span style="color: #66cc66;">&lt;!</span><span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>
&nbsp;
            <span style="color: #0066CC;">import</span> com.<span style="color: #006600;">acme</span>.<span style="color: #006600;">book</span>.<span style="color: #006600;">event</span>.<span style="color: #006600;">GetBookDetailsEvent</span>;
&nbsp;
            <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _bookId:<span style="color: #0066CC;">String</span>;
            <span style="color: #66cc66;">&#91;</span>Bindable<span style="color: #66cc66;">&#93;</span> 
            <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">get</span> bookId<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">String</span> <span style="color: #66cc66;">&#123;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #0066CC;">this</span>._bookId;
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
            <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #0066CC;">set</span> bookId<span style="color: #66cc66;">&#40;</span>newValue:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span> <span style="color: #66cc66;">&#123;</span>
                <span style="color: #0066CC;">this</span>._bookId = newValue;
                <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>bookId<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">new</span> GetBookDetailsEvent<span style="color: #66cc66;">&#40;</span>bookId<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">dispatch</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
                <span style="color: #66cc66;">&#125;</span>
            <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&gt;</span>
    <span style="color: #66cc66;">&lt;/</span>mx:Script<span style="color: #66cc66;">&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;</span>container:ViewStack id=<span style="color: #ff0000;">&quot;viewStack&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span> resizeToContent=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #66cc66;">&gt;</span>
&nbsp;
        <span style="color: #66cc66;">&lt;</span>container:HBox id=<span style="color: #ff0000;">&quot;VIEW_LOADING&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #66cc66;">&gt;</span>
            <span style="color: #66cc66;">&lt;</span>control:Label <span style="color: #0066CC;">htmlText</span>=<span style="color: #ff0000;">&quot;Loading...&quot;</span><span style="color: #66cc66;">/&gt;</span>
        <span style="color: #66cc66;">&lt;/</span>container:HBox<span style="color: #66cc66;">&gt;</span>
&nbsp;
        <span style="color: #66cc66;">&lt;</span>view:BookDetailsView id=<span style="color: #ff0000;">&quot;VIEW_DETAILS&quot;</span> <span style="color: #0066CC;">width</span>=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #66cc66;">/&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;/</span>container:ViewStack<span style="color: #66cc66;">&gt;</span>
&nbsp;
<span style="color: #66cc66;">&lt;/</span>module:ModuleBase<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>So when the module has loaded and receives a change in the bookId property, the module is responsible for the logic of going out to get the data (dispatches the GetBookDetailsEvent).  All logic related to displaying book details is then contained in the module and is not loaded until explicitly referenced by the main app.</p>
<p>In the main application, the module can then be used like this:</p>

<div class="wp_syntax"><div class="code"><pre class="mxml mxml" style="font-family:monospace;">. . .
        <span style="color: #000000;"><span style="color: #7400FF;">&lt;container:ViewStack</span> id=<span style="color: #ff0000;">&quot;viewStack&quot;</span> resizeToContent=<span style="color: #ff0000;">&quot;true&quot;</span> width=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #7400FF;">&gt;</span></span>
&nbsp;
            <span style="color: #000000;"><span style="color: #7400FF;">&lt;view:HomePageView</span> id=<span style="color: #ff0000;">&quot;VIEW_HOME_PAGE&quot;</span> label=<span style="color: #ff0000;">&quot;home&quot;</span><span style="color: #7400FF;">/&gt;</span></span>
&nbsp;
            <span style="color: #000000;"><span style="color: #7400FF;">&lt;module:BookDetailsModuleLoader</span> id=<span style="color: #ff0000;">&quot;VIEW_BOOK_DETAILS&quot;</span> </span>
<span style="color: #000000;">                url=<span style="color: #ff0000;">&quot;BookDetailsModule.swf&quot;</span> label=<span style="color: #ff0000;">&quot;bookDetails&quot;</span> </span>
<span style="color: #000000;">                width=<span style="color: #ff0000;">&quot;100%&quot;</span> height=<span style="color: #ff0000;">&quot;100%&quot;</span><span style="color: #7400FF;">/&gt;</span></span>
. . .</pre></div></div>

<p>In this case, when the VIEW_BOOK_DETAILS module loader is selected as the current child in the viewstack, the module is loaded.  You can now use the urlKit features to load the details for a particular book (with id 12) by deep-linking your browser to:</p>

<div class="wp_syntax"><div class="code"><pre class="url" style="font-family:monospace;">http://myhost/myapp/#/bookDetails/12</pre></div></div>

<p>Or you can reference the module via the module loader in code:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript actionscript" style="font-family:monospace;">. . .
<span style="color: #006600;">VIEW_BOOK_DETAILS</span>.<span style="color: #006600;">bookId</span> = <span style="color: #cc66cc;">12</span>;
VIEW_BOOK_DETAILS.<span style="color: #006600;">loadModule</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
...</pre></div></div>

<p>In real life, you&#8217;d probably also have a view facade or command that ends up setting the bookId property and selecting the VIEW_BOOK_DETAILS as the active view in the viewstack.  That way, you can very simply load up the book details from code, even from another module.</p>
<p>Clearly, there&#8217;s a bunch more &#8220;meat&#8221; behind the real application than what is shown here, but hopefully this demonstrates a solution to working with modules and deep-linking.  If not, please post comments with questions and I&#8217;ll follow up.</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/11/a-flex-implementation-using-modules-with-urlkit-deep-linking/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Production-Grade Acegi Security for Grails</title>
		<link>http://bildtsen.com/2008/11/production-grade-acegi-security-for-grails/</link>
		<comments>http://bildtsen.com/2008/11/production-grade-acegi-security-for-grails/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 17:49:08 +0000</pubDate>
		<dc:creator>Ola Bildtsen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://bildtsen.com/?p=3</guid>
		<description><![CDATA[Note: See an update/upgrade to this post (moving to SpringSecurity) here.
The standard Acegi plugin for Grails provides a basic implementation of the Acegi security framework for the Grails web stack.  It does a nice job of setting up a basic filter chain that can be rather cumbersome to establish from scratch.  It comes hard-wired with [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> See an update/upgrade to this post (moving to SpringSecurity) <a href="http://bildtsen.com/?p=122">here</a>.</p>
<p>The <a href="http://docs.codehaus.org/display/GRAILS/AcegiSecurity%20Plugin%20-%20Basic%20Tutorial">standard Acegi plugin for Grails</a> provides a basic implementation of the Acegi security framework for the Grails web stack.  It does a nice job of setting up a basic filter chain that can be rather cumbersome to establish from scratch.  It comes hard-wired with a simple DAO-based authentication provider, and includes the pieces needed to create a rudimentary security scheme for your Grails application.</p>
<p>But the standard plugin is not very flexible, and does not provide alternate means of authentication (such as LDAP).  It is also cumbersome to configure, and it is difficult to manage authorization mappings.  I also didn&#8217;t like the &#8220;optimistic&#8221; authorization scheme (anything not locked down is publicly available).  This article demonstrates a security plugin implementation for Grails that meets a higher level of security requirements.</p>
<p><span id="more-3"></span></p>
<h2>Basic Acegi Security Concepts</h2>
<p>Let’s first define some security terminology for the purposes of this discussion.  Specifically, there are two components of web security that will be discussed here &#8212; authentication and authorization:</p>
<ul>
<li><strong>Authentication</strong> is the process of verifying a user’s identity, typically done using a simple username/password combination.  When a user is successfully authenticated, Acegi places an authentication token on the HTTP session.  This token contains some information about the authenticated user, including the list of “granted authorities” or “roles” that the user is endowed with.  The authentication token remains active for the life of the HTTP session, or until the user explicitly logs out.</li>
<li>An <strong>authorization</strong> scheme determines which URLs or resources an authenticated user has access to.  For each HTTP request, Acegi compares the list of roles on the authentication token to the roles that are granted access to the target of the request.  If a match is not found, the user is denied access to the resource.</li>
</ul>
<p>This sample plugin is set up with an AnonymousProcessingFilter, which means that an anonymous authentication token is placed on the session with the initial HTTP request.  This token is associated with only one, anonymous role.  This means the authorization scheme works for general access, by assigning that anonymous role to those resources that should be publicly available.</p>
<h2>Higher-level Requirements</h2>
<p>The standard Acegi plugin for Grails does not provide enough flexibility, configurability, or maintainability for a non-trivial production environment.  These are the most important pieces I felt were missing:</p>
<ul>
<li> <strong>Flexible configuration</strong>.  It should be easy to set up, and to get a quick overview of the configuration settings.  Also, environment-specific configuration is a must.</li>
<li><strong>Multiple authentication providers</strong>.  Provide LDAP authentication in addition to the standard DAO implementation.</li>
<li><strong>Pessimistic authorization scheme</strong>.  Default to no access for anybody to anything, open up holes as needed.  This may not work for everybody, but my goal is to reduce the risk of leaving unintended content out there (given how easy it is to implement a Grails controller method).</li>
<li><strong>Ease of implementation</strong>.  A developer should readily be able to configure a controller method to a certain security level at the time of feature implementation.  While I believe security should be an implementation-time decision, it should NOT be an obstacle to rapid and agile development.</li>
<li><strong>Good maintainability</strong>.  When Grails controllers are re-factored or removed, it should be obvious what changes need to be made from a security perspective.   Changes in controller structure should not result in hours of tracing down security rules.</li>
</ul>
<h2>A Solution</h2>
<p>I wanted a security plugin that would perform those two basic tasks of authentication and authorization, while conforming to the five major requirements outlined above.  The simplest way to explain the implementation is to walk through the various pieces and their usage step by step in a sample Grails application.</p>
<h3>Install the Demo</h3>
<p>Start by expanding the <a rel="attachment wp-att-34" href="http://bildtsen.com/?attachment_id=34">demo zip file</a> in a directory of your choosing.  All further project-related paths in this article will assume that you are currently in that top-level install directory.</p>
<p>Notice how there are two grails projects: demo and demo-acegi.  The former is the sample application, while the latter is the acegi plugin.</p>
<p>You will need <a href="http://grails.org/Installation">Grails installed</a> to be able to run the demo, but that&#8217;s not needed for the purposes of this discussion.</p>
<h3>Configuration</h3>
<p>The configuration of the acegi plugin is governed by the application that uses it.  So we&#8217;ll find the acegi settings for our demo application in the application&#8217;s standard configuration file (<code>acegi-plugin-demo/demo/grails-app/conf/Config.groovy</code>).</p>
<p>There are three sets of configuration variables:  The first three variables set up some of the URLs that Acegi needs under various conditions.  The second set of variables sets up the DAO authentication providers, while the last set configures the LDAP authentication providers:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy groovy" style="font-family:monospace;">acegi.<span style="color: #006600;">loginFormUrl</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">'/access/notAuthorized'</span>
acegi.<span style="color: #006600;">logoutUrl</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">'/access/logout'</span>
acegi.<span style="color: #006600;">sessionExpiredUrl</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">'/access/sessionExpired'</span>
<span style="color: #808080; font-style: italic;">// These are the DAO user details services</span>
acegi.<span style="color: #006600;">daoServices</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>
    <span style="color: #ff0000;">'DemoDAO'</span>: <span style="color: #66cc66;">&#91;</span>
        daoService: <span style="color: #ff0000;">'userLookupService'</span>,
        processesUrl: <span style="color: #ff0000;">'/j_acegi_security_check'</span>,
        alwaysUseDefaultTargetUrl: <span style="color: #000000; font-weight: bold;">false</span>,
        authenticationSuccessUrl: <span style="color: #ff0000;">'/loginCredentials/list'</span>,
        authenticationFailureUrl: <span style="color: #ff0000;">'/access/authenticationFailure'</span>
    <span style="color: #66cc66;">&#93;</span>
<span style="color: #66cc66;">&#93;</span>
<span style="color: #808080; font-style: italic;">// These are the LDAP authentication services</span>
acegi.<span style="color: #006600;">ldapServices</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>
    <span style="color: #ff0000;">'DemoLDAP'</span>: <span style="color: #66cc66;">&#91;</span>
        url: <span style="color: #ff0000;">'ldap://your.ldap.url/dc=mycorp,dc=local'</span>,
        managerDn: <span style="color: #ff0000;">'CN=Some Title,CN=SomeGroup,DC=mycorp,DC=local'</span>,
        managerPassword: <span style="color: #ff0000;">'mypassword'</span>,
        userSearchBase: <span style="color: #ff0000;">''</span>,
        groupsPath: <span style="color: #ff0000;">'OU=Groups,OU=Production'</span>,
        processesUrl: <span style="color: #ff0000;">'/j_acegi_security_check_ldap'</span>,
        alwaysUseDefaultTargetUrl: <span style="color: #000000; font-weight: bold;">false</span>,
        authenticationSuccessUrl: <span style="color: #ff0000;">'/loginCredentials/list'</span>,
        authenticationFailureUrl: <span style="color: #ff0000;">'/access/authenticationFailure'</span>
    <span style="color: #66cc66;">&#93;</span>
<span style="color: #66cc66;">&#93;</span></pre></div></div>

<p>As the configurations for the plugin are specified in the standard <code>Config.groovy</code> file, you can obviously make the settings environment-dependent in the standard fashion by placing them in the appropriate environment section of that file.</p>
<p>Notice that most of the configuration settings are URLs, and most of those point to various methods on the <code>AccessController</code> &#8212; this is a controller in the application, not the plugin.  That means the application has full control of the various URLs pointed to by Acegi.</p>
<h3>DAO Authentication</h3>
<p>Under Acegi, DAO authentication is based on the <a href="http://www.acegisecurity.org/acegi-security/apidocs/org/acegisecurity/providers/dao/DaoAuthenticationProvider.html">DaoAuthenticationProvider</a> class.  In essence, this provider users a &#8217;service&#8217; to look up a &#8216;user&#8217; to be authenticated.  The service implements the <a href="http://www.acegisecurity.org/acegi-security/apidocs/org/acegisecurity/userdetails/UserDetailsService.html">UserDetailsService</a> interface, which brings back an implementation of <a href="http://www.acegisecurity.org/acegi-security/apidocs/org/acegisecurity/userdetails/UserDetails.html">UserDetails</a> to represent the user.  There are comments in the Acegi API documentation to explain these classes/interfaces in detail.</p>
<p>The DAO authentication provider used in our plugin is more or less the same as used by the standard Acegi plugin for Grails, except our plugin makes it more configurable.  The actual domain classes and the <code>UserDetailsService</code> are provided by the application, not the plugin.  Since Acegi deals with interfaces and doesn&#8217;t need to know anything about the back-end implementation of these items, this provides maximum flexibility.</p>
<p>In the configuration settings for the demo DAO authentication provider, notice the <code>daoService</code> variable.  Its value is set to <code>userLookupService</code>, which is a Spring bean reference to a Grails service declared by the demo application.</p>
<p>That service looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #a1a100;">org.acegisecurity.userdetails.UserDetails</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #a1a100;">org.acegisecurity.userdetails.UsernameNotFoundException</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #a1a100;">org.springframework.dao.DataAccessException</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #a1a100;">org.acegisecurity.userdetails.UserDetailsService</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> UserLookupService <span style="color: #000000; font-weight: bold;">implements</span> UserDetailsService <span style="color: #66cc66;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> UserDetails loadUserByUsername<span style="color: #66cc66;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">String</span> userName<span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> UsernameNotFoundException, DataAccessException <span style="color: #66cc66;">&#123;</span>
        User user <span style="color: #66cc66;">=</span> User.<span style="color: #006600;">findByUsername</span><span style="color: #66cc66;">&#40;</span>userName<span style="color: #66cc66;">&#41;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>user<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            log.<span style="color: #006600;">debug</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;User found for ${userName}: &quot;</span> <span style="color: #66cc66;">+</span> user<span style="color: #66cc66;">&#41;</span>
            <span style="color: #000000; font-weight: bold;">return</span> user
        <span style="color: #66cc66;">&#125;</span>
        log.<span style="color: #006600;">info</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;User NOT found: ${userName}&quot;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> UsernameNotFoundException<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;User not found.&quot;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>This is about as basic an implementation of the Acegi <code>UserDetailsService</code> as it gets.   It simply looks up a <code>UserDetails</code> object based on the username passed in.  The <code>UserDetails</code> object is used by Acegi to create the authentication token mentioned above.</p>
<p>In the demo application, the <code>UserDetails</code> interface is implemented by the Grails domain class <code>User</code>, which has a one-to-many relationship to <code>Role</code>.  Thus, these two Grails domain classes, <code>User</code> and <code>Role</code>, form the basis for the Acegi DAO authentication token in our demo application.  These domain classes are found in the conventional Grails directory, <code>acegi-plugin-demo/demo/grails-app/domain</code>.</p>
<p>In summary, the implementation of the DAO service is completely determined by the application, not the plugin.  As long as a valid UserDetails object is returned, the actual implementation of the daoService bean is irrelevant.</p>
<h3>LDAP Authentication</h3>
<p>Our plugin&#8217;s implementation of an LDAP authentication service is merely offering a convenient way to configure a standard Acegi <a href="http://www.acegisecurity.org/acegi-security/apidocs/index.html?org/acegisecurity/userdetails/UserDetailsService.html">LdapAuthenticationProvider</a>.  There are no additional pieces required by the application beyond the configuration settings as provided in <code>acegi-plugin-demo/demo/conf/Config.groovy</code>.</p>
<p>One thing to keep in mind is that the group names configured in the LDAP system must match the role names used in your application.  Acegi inserts the text &#8216;ROLE_&#8217; to at the beginning of each group name retrieved from LDAP and forces the rest of the group name text to all upper-case.  For instance, if you have a group in your LDAP system named &#8216;SuperUser&#8217;, the role in your authorization mappings should read &#8216;ROLE_SUPERUSER&#8217;.</p>
<h3>Authorization</h3>
<p>In order to reach the goals of easy development and maintainability, it is essential to standardize the definition of url-to-authorization mappings.  In other words, use a convention to determine which roles are permitted to access a URL.</p>
<p>In the standard acegi plugin, these authorization mappings are established by manually entering rules in a database table.  That table is read by the plugin at start-up, and all authorization decisions are based on those rules.  The authorization mappings must be configured, in no direct relation to the resources they govern.</p>
<p>I found this to be cumbersome and error-prone &#8211; a developer working on a controller method had to enter database rows to govern the security access to the code she was working on.  To determine the access level of a particular controller&#8217;s methods, you had to do a rather complex database query.  When the rules got more fine-grained, it became very hard to determine which rule actually applied to which resource.</p>
<p>It would be better to have the authorization mappings defined in the controllers themselves.  The access-level of a URL would then be directly determined right next to the URL end-point that it governs, in a conventional location.</p>
<p>As an example, let&#8217;s examine the controller <code>acegi-plugin-demo/demo/grails-app/controller/UserController.groovy</code> in the demo application:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> UserController <span style="color: #66cc66;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">static</span> authorizations <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span>
        index: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        list: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        show: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        create: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        save: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        edit: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>,
        update: <span style="color: #66cc66;">&#91;</span>Role.<span style="color: #006600;">ADMIN_USER</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#93;</span>
. . .</pre></div></div>

<p>The controller declares a simple map with its methods as keys and a list of roles as values.  In this case, only users with the <code>ADMIN_USER</code> role are granted access to these methods.</p>
<p>There are some URLs in a Grails application that do not correspond to a controller method.   These special-case mappings must be mapped somewhere else.  It seemed the most logical place for that was in the <code>UrlMappings</code> class, as this class contains other mappings that direct traffic around the application.</p>
<p>As an example, let&#8217;s examine the demo application&#8217;s <code>acegi-plugin-demo/demo/conf/UrlMappings.groovy</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> UrlMappings <span style="color: #66cc66;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">static</span> authorizations <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span>
        <span style="color: #ff0000;">'/'</span>: Role.<span style="color: #006600;">ALL_ROLES</span>,
        <span style="color: #ff0000;">'/js/**'</span>: Role.<span style="color: #006600;">ALL_ROLES</span>,
        <span style="color: #ff0000;">'/css/**'</span>: Role.<span style="color: #006600;">ALL_ROLES</span>,
        <span style="color: #ff0000;">'/images/**'</span>: Role.<span style="color: #006600;">ALL_ROLES</span>,
        <span style="color: #ff0000;">'/logout'</span>: Role.<span style="color: #006600;">ALL_ROLES</span>
    <span style="color: #66cc66;">&#93;</span>
. . .</pre></div></div>

<p>These mappings open up access for URLs in a path-based manner, including wild-cards (as supported by Spring&#8217;s <code>AntPathMatcher</code>).  The access paths are the keys and lists of roles are the values.</p>
<p>The authorization mappings declared in <code>UrlMappings</code> are fairly static, and should not be modified by developers.  While you could easily put sweeping rules around controllers in <code>UrlMappings</code>, that would defeat the purpose of our convention-based scheme that has the mappings in the controllers themselves.</p>
<p>In summary, authorization mappings are determined in two conventional places:</p>
<ul class="unIndentedList">
<li> <strong>Controllers.</strong> As almost every URI into the Grails application is through a controller method, this is the best place to maintain the authorization mappings.</li>
<li> <strong>UrlMappings.</strong> Provides a way to establish authorization rules for urls or paths that are not tied to a controller or its methods, e.g. /css/** or /js/**.</li>
</ul>
<h2>Running the Demo</h2>
<p>To start up the application, go to the demo application directory and start grails:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">cd acegi-plugin-demo/demo
grails run-app</pre></div></div>

<p>As the demo application uses a simple HQL database, it creates some bootstrap data in <code>acegi-plugin-demo/demo/grails-app/conf/BootStrap.groovy</code> to create a role and an initial admin user:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy groovy" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// Create a role for the demo application</span>
<span style="color: #000000; font-weight: bold;">new</span> Role<span style="color: #66cc66;">&#40;</span>authority: <span style="color: #ff0000;">'ROLE_ADMIN_USER'</span>, description: <span style="color: #ff0000;">'Administrative User'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">// Create an admin user, and add the admin user role</span>
<span style="color: #000000; font-weight: bold;">def</span> user <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> User<span style="color: #66cc66;">&#40;</span>username: <span style="color: #ff0000;">'adminUser'</span>, password: <span style="color: #ff0000;">'password'</span>.<span style="color: #006600;">encodeAsPassword</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
user.<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
user.<span style="color: #006600;">addToRoles</span><span style="color: #66cc66;">&#40;</span>Role.<span style="color: #006600;">findByAuthority</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'ROLE_ADMIN_USER'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
user.<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Now point your browser to the home page of the application: <a href="http://localhost:8080/demo">http://localhost:8080/demo</a>.</p>
<p>You will see two controllers listed &#8212; <code>UserController</code> and <code>AccessController</code>.  Try clicking UserController.  Notice how you are re-directed to the login page.  This is Acegi re-directing you because you haven&#8217;t authenticated yet.  Login using adminUser/password (as set up in the bootstrap data above), and you will be taken to the default action for the UserController.  This demonstrates how the simple authorizations mappings we set up in <code>UserController</code> above determine how to allow access to controller methods.</p>
<h2>Next Steps</h2>
<p>This article covers the main goals and uses of an alternative Acegi plugin for Grails.  It does not go into the details of the plugin implementation, nor does it do a terribly good job of explaining the meaning of the configurable URLs that are used by the Acegi decision process.  It is my hope that the code/examples are self-documenting, but I can understand if things are unclear &#8212; especially if you are not already familiar with the workings of the Acegi framework.</p>
<p>This plugin can also be used with a finer-grained authorization scheme that associates permissions to roles.  This allows an application to have fairly coarse-grained roles that rarely change, while finer-grained permissions maintained by the application are directly linked to access privileges on a very low level (like which buttons are enabled on a particular screen, etc.).  But this is a topic for another post/article, so as not to confuse you further at this point.</p>
<p>Please post your comments/suggestions, and I will follow up with more posts as needed.  I am planning a post on the inner workings of the plugin, but right now I&#8217;m spent&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://bildtsen.com/2008/11/production-grade-acegi-security-for-grails/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
