<?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>Oliver's Place &#187; Web Development</title>
	<atom:link href="http://weichhold.com/category/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://weichhold.com</link>
	<description></description>
	<lastBuildDate>Thu, 12 Aug 2010 18:13:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>High performance Grails with memcached</title>
		<link>http://weichhold.com/2010/03/04/high-performance-grails-with-memcached/</link>
		<comments>http://weichhold.com/2010/03/04/high-performance-grails-with-memcached/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 21:28:24 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=148</guid>
		<description><![CDATA[This article is the second one in my article series about fast loading web pages. The first article dealt with the Django Framework while this one is about Grails which I have recently elected as my preferred rapid web application framework. Ever since I switched from Django to Grails there was one issue that bothered [...]]]></description>
			<content:encoded><![CDATA[<p>This article is the second one in my article series about fast loading web pages. The first article dealt with the <a href="http://www.djangoproject.com/">Django Framework</a> while this one is about <a href="http://grails.org">Grails </a>which I have recently elected as my preferred rapid web application framework. Ever since I switched from Django to Grails there was one issue that bothered me and that was the loss of the ability to serve complete pre-rendered pages from a distributed cache to the enduser while bypassing the application server.</p>
<p>The solution described in this article is in use on the production servers powering <a href="http://mmogle.com">mmogle.com</a> where it ensures page response times below 100ms for cached content.</p>
<p>Let me summarize the concept for readers not familiar with my first article: The goal we want to achieve is to greatly decrease the load on the application server (container) by storing the raw HTML output of rendered pages in a (distributed-) cache to be picked up by a Frontend Web Server without even bothering the application server behind it for the current request. Since we would need stuff like Edge Side Includes (ESI) for dealing with personalized pages, we are going limit ourselves to anonymous users.</p>
<p><span id="more-148"></span></p>
<p>This picture below shows the server setup:</p>

<a href="http://weichhold.com/wp-content/gallery/misc/nginx-memcached.png" title="" class="thickbox" rel="singlepic8" >
	<img class="ngg-singlepic" src="http://weichhold.com/wp-content/plugins/nextgen-gallery/nggshow.php?pid=8&amp;width=420&amp;height=&amp;mode=" alt="nginx-memcached" title="nginx-memcached" />
</a>

<p><a href="http://wiki.nginx.org/Main">Nginx </a>will act as frontend web server. This is where all requests will initially arrive. Requests for static resources will always be handled by nginx. Dynamic requests will be scrutinized and once it is determined that a request could be cached, a cache key is computed based on request URI, cookies etc. Nginx will then proceed with querying memcached if one of the application servers has deposited content under that key. If the answer is positive the response from memcached is directly returned to the client – the application servers are bypassed. Perhaps it is worth noting that the application server (tomcat) is only responsible for storing the content, whereas nginx &#8211; acting as frontend server &#8211; is responsible for retrieving it. This decoupling is what sets this technique apart from the Grails Cache Filter Plugin which both stores and retrieves cached content.</p>
<p>Let’s continue with the actual implementation. When I decided to port the technique I described in the aforementioned article from Python/Django to Groovy/Grails, I thought it was going to be a very easy task. All that’s needed is to grab the rendered page contents within a Grails afterView Filter, put it into memcached and be done with it, right? Wrong! Imagine my surprise when I noticed the rendered output never had a layout applied. After lots of trying I gave up, realising that there is simply no way to get my hands on the <strong>complete </strong>HTML (emphasis on <em>complete</em>) for a rendered Grails page from within the application itself. The reason for this is Grails layouts are based on Sitemesh which is implemented as a ServletFilter. Grails applies the Layout to pages through its GrailsPageFilter ServletFilter which is executed further down in the pipeline after any Grails Filters.</p>
<p>That left me with only one option: a custom ServletFilter that executes before GrailsPageFilter. So I checked out the source of the <a href="http://www.grails.org/plugin/cachefilter">Grails Cache Filter Plugin</a>, stripped it off anything not necessary for our purpose and born was MemcachedFilter. You can download the source <a href="http://weichhold.com/MemcachedFilter.zip">here</a>.</p>
<p>MemcachedFilter is written in Groovy and it needs to be configured to execute before GrailsPageFilter. That means that it’s filter mapping element must appear before the filter mapping for GrailsPageFilter in web.xml. Here’s a sample web.xml snippet:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p148code5'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1485"><td class="code" id="p148code5"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>memcached<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.banshee.servlet.MemcachedFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!-- memcached filter --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>memcached<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>charEncodingFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>sitemesh<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>MemcachedFilter has a dependency on a bean named “memcachedClient”. Please <a href="http://weichhold.com/2009/09/17/configuring-memcached-in-a-grails-application/">refer to this article</a> for configuration instructions.</p>
<p>Now that the filter is configured and active we actually want to put it to use – which is quite easy. The filter scans all Responses it encounters for the presence of two special headers: &#8220;X-Memcached-Filter-Cache-Key&#8221; and &#8220;X-Memcached-Filter-Cache-Timeout&#8221; (the latter is optional). If the &#8220;X-Memcached-Filter-Cache-Key&#8221; is detected the filter will store the response content in memcached using the header value as key. The expiration timeout will be either a default value or the value of the &#8220;X-Memcached-Filter-Cache-Timeout&#8221; header. It’s that simple. Here’s a usage example:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p148code6'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1486"><td class="code" id="p148code6"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> FooController
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">def</span> index <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span>SecurityUtils.<span style="color: #006600;">subject</span>.<span style="color: #006600;">principal</span><span style="color: #66cc66;">&#41;</span>      <span style="color: #808080; font-style: italic;">// store response only for anonymous users (using Shiro plugin)</span>
    <span style="color: #66cc66;">&#123;</span>
      response.<span style="color: #006600;">setHeader</span><span style="color: #66cc66;">&#40;</span>MemcachedFilter.<span style="color: #006600;">MEMCACHED_FILTER_X_CACHE_KEY</span>, ConfigurationHolder.<span style="color: #006600;">config</span>.<span style="color: #006600;">app_prefix</span> <span style="color: #66cc66;">+</span> <span style="color: #66cc66;">&#40;</span>request.<span style="color: #006600;">forwardURI</span> <span style="color: #66cc66;">-</span> request.<span style="color: #006600;">contextPath</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
      response.<span style="color: #006600;">setHeader</span><span style="color: #66cc66;">&#40;</span>MemcachedFilter.<span style="color: #006600;">MEMCACHED_FILTER_X_CACHE_TIMEOUT</span>, <span style="color: #cc66cc;">120</span><span style="color: #66cc66;">&#41;</span>         <span style="color: #808080; font-style: italic;">// cache for two minutes</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>This will store the response content for FooController’s ‘index’ action in memcached for two minutes using the context relative request URI as cache key as long as the requesting user is not logged in. It is of paramount importance that you never ever do this for authenticated users or bad things may happen. You don’t want John Doe to access information intended for the boss, only because the boss happened to be the first user accessing a certain page, do you? To make sure that our Frontend server will try fetch content from the cache for authenticated users we need a way for it to tell if a request is from an anonymous or authenticated user. To do this I wrote a simple Grails Filter that ensures that authenticated users are tagged with a cookie:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p148code7'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1487"><td class="code" id="p148code7"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> CacheFilters
<span style="color: #66cc66;">&#123;</span>
  CacheService questionCacheService
&nbsp;
  <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #aaaadd; font-weight: bold;">String</span> MEMCACHED_USER_IS_AUTH_INDICATOR_COOKIE <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'user_id'</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">def</span> filters <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">/** Sets or deletes a cookie that signals nginx that the current user is authenticated - not used for permission checks */</span>
    setNginxUserIsAuthenticatedIndicator<span style="color: #66cc66;">&#40;</span>controller: <span style="color: #ff0000;">'*'</span>, action: <span style="color: #ff0000;">'*'</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
      afterView <span style="color: #66cc66;">=</span>
      <span style="color: #66cc66;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> cookie <span style="color: #66cc66;">=</span> request.<span style="color: #006600;">cookies</span>.<span style="color: #663399;">find</span> <span style="color: #66cc66;">&#123;</span> it.<span style="color: #006600;">name</span> <span style="color: #66cc66;">==</span> MEMCACHED_USER_IS_AUTH_INDICATOR_COOKIE <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">// is the user authenticated (by login or cookie?)</span>
        <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>SecurityUtils.<span style="color: #006600;">subject</span>.<span style="color: #006600;">principal</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
          <span style="color: #808080; font-style: italic;">// yes, set the cookie if needed</span>
          <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span>cookie<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#123;</span>
            cookie <span style="color: #66cc66;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Cookie<span style="color: #66cc66;">&#40;</span>MEMCACHED_USER_IS_AUTH_INDICATOR_COOKIE, User.<span style="color: #663399;">get</span><span style="color: #66cc66;">&#40;</span>SecurityUtils.<span style="color: #006600;">subject</span>.<span style="color: #006600;">principal</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">id</span>.<span style="color: #006600;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
            cookie.<span style="color: #006600;">setPath</span><span style="color: #66cc66;">&#40;</span>request.<span style="color: #006600;">getContextPath</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
            response.<span style="color: #006600;">addCookie</span><span style="color: #66cc66;">&#40;</span>cookie<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#125;</span>
        <span style="color: #66cc66;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">else</span>
        <span style="color: #66cc66;">&#123;</span>
          <span style="color: #808080; font-style: italic;">// delete the cookie if necessary</span>
          <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>cookie<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#123;</span>
            cookie.<span style="color: #006600;">setMaxAge</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
            cookie.<span style="color: #006600;">setPath</span><span style="color: #66cc66;">&#40;</span>request.<span style="color: #006600;">getContextPath</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
            response.<span style="color: #006600;">addCookie</span><span style="color: #66cc66;">&#40;</span>cookie<span style="color: #66cc66;">&#41;</span>
          <span style="color: #66cc66;">&#125;</span>
        <span style="color: #66cc66;">&#125;</span>
      <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>Rest assured that the sole purpose of the cookie is to signal the frontend server that a user is authenticated in order to disable any cache retrieval attempts. No security checks are ever performed against the cookie.</p>
<p>Now that we’ve taken care of storing the content, someone has to retrieve it. As already mentioned we are using Nginx as Frontend server. I’m a big fan of it because of its small footprint, great performance and integrated support for memcached. Below is a Nginx virtual host configuration that implements the remaining bits and pieces:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p148code8'); return false;">View Code</a> APACHE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1488"><td class="code" id="p148code8"><pre class="apache" style="font-family:monospace;">upstream tomcats
{
  server 127.0.0.1:<span style="color: #ff0000;">8080</span> weight=<span style="color: #ff0000;">1</span>;
}
&nbsp;
server
{
  <span style="color: #00007f;">listen</span> <span style="color: #ff0000;">80</span>;
  server_name example.com;
  access_log /var/log/nginx/example.log;
&nbsp;
  <span style="color: #00007f;">include</span> ua_ban_list.conf;
&nbsp;
  proxy_set_header Host $http_host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&nbsp;
  default_type text/html;
  charset utf-<span style="color: #ff0000;">8</span>;
&nbsp;
  proxy_redirect http://tomcats/ http://example.com/;
&nbsp;
  location /
  {
    <span style="color: #adadad; font-style: italic;"># only consider GET requests for caching</span>
    if ($request_method != GET)
    {
      proxy_pass http://tomcats;
      break;
    }
&nbsp;
    <span style="color: #adadad; font-style: italic;"># never cache auth requests</span>
    if ($request_uri ~* (^/auth/.*$))
    {
      proxy_pass http://tomcats;
      break;
    }
&nbsp;
    <span style="color: #adadad; font-style: italic;"># detect cookies that indicate an authenticated user</span>
    if ($http_cookie ~* <span style="color: #7f007f;">&quot;(rememberMe|user_id)&quot;</span>)
    {
      <span style="color: #adadad; font-style: italic;"># don't try cache lookup for authenticated user - NEVER</span>
      proxy_pass http://tomcats;
      break;
    }
&nbsp;
    <span style="color: #adadad; font-style: italic;"># compute cache key from app prefix + request_uri</span>
    <span style="color: #adadad; font-style: italic;"># if they computed key does not match the key computed by the application</span>
    <span style="color: #adadad; font-style: italic;"># server when storing content we will get nothing but memcached misses</span>
    <span style="color: #adadad; font-style: italic;"># and NO speedup</span>
    set $memcached_key example_$request_uri;
    memcached_pass memcached;
    error_page <span style="color: #ff0000;">404</span> = @cache_miss;
  }
&nbsp;
  location @cache_miss
  {
    internal;
    proxy_pass http://tomcats;
  }
}</pre></td></tr></table></div>

<p>Please pay special attention to the line where the cache key is computed. A key prefix &#8220;example_&#8221; is used. To get the example to work you would have to add a config variable &#8216;app_prefix&#8217; to Config.groovy which needs to have the value &#8220;example_&#8221;.</p>
<p>Finally I should point out that this approach isn&#8217;t tied to Grails applications. Basically any Java Web application could use it if someone would port the MemcachedFilter from Groovy to Java which should be a piece of cake considering that it was developed from Java Sources in the first place.</p>
<p>That&#8217;s it for now. I hope you enjoyed the ride.</p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=148&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2010/03/04/high-performance-grails-with-memcached/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple GSP toolbar taglib for Grails</title>
		<link>http://weichhold.com/2010/01/13/a-simple-gsp-toolbar-taglib-for-grails/</link>
		<comments>http://weichhold.com/2010/01/13/a-simple-gsp-toolbar-taglib-for-grails/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 15:55:26 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=112</guid>
		<description><![CDATA[Did you ever had to implement a menu in Grails GSP where every link element should be seperated from its predecessor by a separator character and where some of the elements can be missing when certain conditions are not met (security etc)? The part with the optional elements can turn the separator handling into a [...]]]></description>
			<content:encoded><![CDATA[<p>Did you ever had to implement a menu in Grails GSP where every link element should be seperated from its predecessor by a separator character and where some of the elements can be missing when certain conditions are not met (security etc)?</p>
<p>The part with the optional elements can turn the separator handling into a real mess. So today I decided to end this nonsense. The result is a tiny taglib which can be integrated into every grails project. The usage is pretty self explanatory:</p>
<p><b><br />
&lt;mx:toolbar separator=&#8217;|'&gt;<br />
&nbsp;&nbsp;&lt;mx:item&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;shiro:hasPermission permission=&#8221;topic:delete&#8221;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;g:link controller=&#8221;topic&#8221; action=&#8221;delete&#8221; id=&#8221;${topic.id}&#8221;&gt;&lt;g:message code=&#8221;topic.delete&#8221;&gt;&lt;/g:message&gt;&lt;/g:link&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/shiro:hasPermission&gt;<br />
&nbsp;&nbsp;&lt;/mx:item&gt;</p>
<p>&nbsp;&nbsp;&lt;mx:item&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;shiro:hasPermission permission=&#8221;topic:lock&#8221;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;g:link controller=&#8221;topic&#8221; action=&#8221;lock&#8221; id=&#8221;${topic.id}&#8221;&gt;&lt;g:message code=&#8221;topic.lock&#8221;&gt;&lt;/g:message&gt;&lt;/g:link&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/shiro:hasPermission&gt;<br />
&nbsp;&nbsp;&lt;/mx:item&gt;<br />
&lt;/mx:toolbar&gt;<br />
</b></p>
<p><span id="more-112"></span></p>
<p>And this would be rendered assuming the user has permission for both buttons:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p112code11'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p11211"><td class="code" id="p112code11"><pre class="html" style="font-family:monospace;">&lt;a href=&quot;/topic/delete/10&quot;&gt;Delete&lt;/a&gt;|&lt;a href=&quot;/topic/lock/10&quot;&gt;Lock&lt;/a&gt;</pre></td></tr></table></div>

<p>Tag Library Source:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p112code12'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p11212"><td class="code" id="p112code12"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> MenuTagLib
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">static</span> namespace <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'mx'</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/** The toolbar container */</span>
  <span style="color: #000000; font-weight: bold;">def</span> toolbar <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span> attrs, body <span style="color: #66cc66;">-&gt;</span>
    <span style="color: #000000; font-weight: bold;">def</span> separator <span style="color: #66cc66;">=</span> attrs.<span style="color: #006600;">separator</span> <span style="color: #66cc66;">?</span>: <span style="color: #ff0000;">'|'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// we'll be using this to keep track of our items</span>
    <span style="color: #000000; font-weight: bold;">def</span> menuItems <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006600;">pageScope</span>.<span style="color: #006600;">menuItems</span> <span style="color: #66cc66;">=</span> menuItems
&nbsp;
    <span style="color: #808080; font-style: italic;">// this will execute the body, so that the items are appended obviously,</span>
    <span style="color: #808080; font-style: italic;">// anything other than the item tags will not render correctly.</span>
    body<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// render every item and add a separator except for the last item </span>
    menuItems.<span style="color: #663399;">eachWithIndex</span>
    <span style="color: #66cc66;">&#123;</span> item, index <span style="color: #66cc66;">-&gt;</span>
      out <span style="color: #66cc66;">&lt;&lt;</span> item
      <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>index <span style="color: #66cc66;">&lt;</span> menuItems.<span style="color: #663399;">size</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>
        out <span style="color: #66cc66;">&lt;&lt;</span> separator
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">/** A toolbar item */</span>
  <span style="color: #000000; font-weight: bold;">def</span> item <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span> attrs, body <span style="color: #66cc66;">-&gt;</span>
    <span style="color: #000000; font-weight: bold;">def</span> itemContent <span style="color: #66cc66;">=</span> body<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">trim</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>itemContent<span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">// only add the item if rendering evaluated to non-empty string</span>
      <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006600;">pageScope</span>.<span style="color: #006600;">menuItems</span> <span style="color: #66cc66;">&lt;&lt;</span> itemContent
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<img src="http://weichhold.com/?ak_action=api_record_view&id=112&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2010/01/13/a-simple-gsp-toolbar-taglib-for-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails sanitized stracktraces</title>
		<link>http://weichhold.com/2009/10/10/grails-sanitized-stracktraces/</link>
		<comments>http://weichhold.com/2009/10/10/grails-sanitized-stracktraces/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 21:01:35 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=107</guid>
		<description><![CDATA[The other day I was writing a medium complex HQL query for a Grails App and no matter what the line executing the query would crash like this: ?View Code GROOVYjava.lang.NullPointerException at $Proxy13.createQuery&#40;Unknown Source&#41; at com.acme.PerformanceService.makePerformanceSheet&#40;PerformanceService.groovy:38&#41; ... So how the hell do we figure out what the problem given so few information? Turns out that [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I was writing a medium complex HQL query for a Grails App and no matter what the line executing the query would crash like this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p107code16'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p10716"><td class="code" id="p107code16"><pre class="groovy" style="font-family:monospace;">java.<span style="color: #006600;">lang</span>.<span style="color: #aaaadd; font-weight: bold;">NullPointerException</span>
	at $Proxy13.<span style="color: #006600;">createQuery</span><span style="color: #66cc66;">&#40;</span>Unknown Source<span style="color: #66cc66;">&#41;</span>
	at com.<span style="color: #006600;">acme</span>.<span style="color: #006600;">PerformanceService</span>.<span style="color: #006600;">makePerformanceSheet</span><span style="color: #66cc66;">&#40;</span>PerformanceService.<span style="color: #006600;">groovy</span>:<span style="color: #cc66cc;">38</span><span style="color: #66cc66;">&#41;</span>
  ...</pre></td></tr></table></div>

<p>So how the hell do we figure out what the problem given so few information? Turns out that grails sanitizes the exception stacktrace, resulting in better readability by removing a lot of clutter. Sometimes though this optimization will also hide some important details from you. Luckily we can still refer to stacktrace.log which usually resides in the project root folder in development mode. In this particular case opening the file reveiled this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p107code17'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p10717"><td class="code" id="p107code17"><pre class="groovy" style="font-family:monospace;">java.<span style="color: #006600;">lang</span>.<span style="color: #aaaadd; font-weight: bold;">NullPointerException</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">dialect</span>.<span style="color: #006600;">Dialect</span>$<span style="color: #cc66cc;">3</span>.<span style="color: #006600;">getReturnType</span><span style="color: #66cc66;">&#40;</span>Dialect.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">125</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">util</span>.<span style="color: #006600;">SessionFactoryHelper</span>.<span style="color: #006600;">findFunctionReturnType</span><span style="color: #66cc66;">&#40;</span>SessionFactoryHelper.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">405</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">tree</span>.<span style="color: #006600;">AggregateNode</span>.<span style="color: #006600;">getDataType</span><span style="color: #66cc66;">&#40;</span>AggregateNode.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">44</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">tree</span>.<span style="color: #006600;">SelectClause</span>.<span style="color: #006600;">initializeExplicitSelectClause</span><span style="color: #66cc66;">&#40;</span>SelectClause.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">165</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">HqlSqlWalker</span>.<span style="color: #006600;">useSelectClause</span><span style="color: #66cc66;">&#40;</span>HqlSqlWalker.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">727</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">HqlSqlWalker</span>.<span style="color: #006600;">processQuery</span><span style="color: #66cc66;">&#40;</span>HqlSqlWalker.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">551</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">antlr</span>.<span style="color: #006600;">HqlSqlBaseWalker</span>.<span style="color: #006600;">query</span><span style="color: #66cc66;">&#40;</span>HqlSqlBaseWalker.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">645</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">antlr</span>.<span style="color: #006600;">HqlSqlBaseWalker</span>.<span style="color: #006600;">selectStatement</span><span style="color: #66cc66;">&#40;</span>HqlSqlBaseWalker.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">281</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">antlr</span>.<span style="color: #006600;">HqlSqlBaseWalker</span>.<span style="color: #006600;">statement</span><span style="color: #66cc66;">&#40;</span>HqlSqlBaseWalker.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">229</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">QueryTranslatorImpl</span>.<span style="color: #006600;">analyze</span><span style="color: #66cc66;">&#40;</span>QueryTranslatorImpl.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">251</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">QueryTranslatorImpl</span>.<span style="color: #006600;">doCompile</span><span style="color: #66cc66;">&#40;</span>QueryTranslatorImpl.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">183</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">QueryTranslatorImpl</span>.<span style="color: #006600;">compile</span><span style="color: #66cc66;">&#40;</span>QueryTranslatorImpl.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">134</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">engine</span>.<span style="color: #006600;">query</span>.<span style="color: #006600;">HQLQueryPlan</span>.<span style="color: #66cc66;">&lt;</span>init<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>HQLQueryPlan.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">101</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">engine</span>.<span style="color: #006600;">query</span>.<span style="color: #006600;">HQLQueryPlan</span>.<span style="color: #66cc66;">&lt;</span>init<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>HQLQueryPlan.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">80</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">engine</span>.<span style="color: #006600;">query</span>.<span style="color: #006600;">QueryPlanCache</span>.<span style="color: #006600;">getHQLQueryPlan</span><span style="color: #66cc66;">&#40;</span>QueryPlanCache.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">94</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">impl</span>.<span style="color: #006600;">AbstractSessionImpl</span>.<span style="color: #006600;">getHQLQueryPlan</span><span style="color: #66cc66;">&#40;</span>AbstractSessionImpl.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">156</span><span style="color: #66cc66;">&#41;</span>
	at org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">impl</span>.<span style="color: #006600;">AbstractSessionImpl</span>.<span style="color: #006600;">createQuery</span><span style="color: #66cc66;">&#40;</span>AbstractSessionImpl.<span style="color: #006600;">java</span>:<span style="color: #cc66cc;">135</span><span style="color: #66cc66;">&#41;</span>
  ...</pre></td></tr></table></div>

<p>Which almost instantly gave me the hint that something&#8217;s wrong with the aggregate part of my query:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p107code18'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p10718"><td class="code" id="p107code18"><pre class="groovy" style="font-family:monospace;">org.<span style="color: #006600;">hibernate</span>.<span style="color: #006600;">hql</span>.<span style="color: #006600;">ast</span>.<span style="color: #006600;">tree</span>.<span style="color: #006600;">AggregateNode</span>.<span style="color: #006600;">getDataType</span></pre></td></tr></table></div>

<p>And indeed the problem was that I had ported an SQL Query to HQL and forgot to rename the sum() aggregate argument from the column name to the domain class property name:</p>
<p>sum(some_property) instead of sum(foo.someProperty)</p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=107&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/10/10/grails-sanitized-stracktraces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuring memcached in a Grails Application</title>
		<link>http://weichhold.com/2009/09/17/configuring-memcached-in-a-grails-application/</link>
		<comments>http://weichhold.com/2009/09/17/configuring-memcached-in-a-grails-application/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 11:13:31 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=95</guid>
		<description><![CDATA[I&#8217;m a big fan of using memcached for improving the scalability of websites so when I recently fell in love with the Grails Framework I began to look for a way to configure the memcached client which blends in with the framework. Luckily Grails provides a very easy way to configure Spring Beans using a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of using memcached for improving the scalability of websites so when I recently fell in love with the <a href="http://grails.org" target="_blank">Grails Framework </a>I began to look for a way to configure the memcached client which blends in with the framework. Luckily Grails provides a very easy way to configure Spring Beans using a DSL Just create grails-app/conf/spring/resources.groovy and add this:<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p95code21'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p9521"><td class="code" id="p95code21"><pre class="groovy" style="font-family:monospace;">beans <span style="color: #66cc66;">=</span>
<span style="color: #66cc66;">&#123;</span>
  memcachedClient<span style="color: #66cc66;">&#40;</span>MemcachedClient, 
    net.<span style="color: #006600;">spy</span>.<span style="color: #006600;">memcached</span>.<span style="color: #006600;">AddrUtil</span>.<span style="color: #006600;">getAddresses</span><span style="color: #66cc66;">&#40;</span>
      ConfigurationHolder.<span style="color: #006600;">config</span>.<span style="color: #006600;">memcached_servers</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span> bean <span style="color: #66cc66;">-&gt;</span>
    bean.<span style="color: #006600;">scope</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'singleton'</span> 
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>Voila, from now on you can get a  memcached client instance anywhere in your application either by standard dependency injection or by calling applicationContext.getBean(&#8216;memcachedClient&#8217;).</p>
<p>It is important to note that this example assumes that you have configured your memcached server(s) in grails-app/conf/Config.groovy like this:<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p95code22'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p9522"><td class="code" id="p95code22"><pre class="groovy" style="font-family:monospace;">environments
<span style="color: #66cc66;">&#123;</span>
  development
  <span style="color: #66cc66;">&#123;</span>
    memcached_servers <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;192.168.230.2:11211&quot;</span>
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  production
  <span style="color: #66cc66;">&#123;</span>
    memcached_servers <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;localhost:11211&quot;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<img src="http://weichhold.com/?ak_action=api_record_view&id=95&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/09/17/configuring-memcached-in-a-grails-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Updating multiple page elements with Grails and Ajax</title>
		<link>http://weichhold.com/2009/07/20/updating-multiple-page-fragments-with-grails-and-ajax/</link>
		<comments>http://weichhold.com/2009/07/20/updating-multiple-page-fragments-with-grails-and-ajax/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 09:30:01 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=39</guid>
		<description><![CDATA[Every Web Application Project I’ve been involved in the recent past had one thing in common: the client demanded more and more rich-client features at an ever increasing pace &#8211; without committing itself to real rich-client frameworks such as Flex or Silverlight. This leaves us with Javascript / AJAX for implementing highly dynamic User Interfaces [...]]]></description>
			<content:encoded><![CDATA[<p>Every Web Application Project I’ve been involved in the recent past had one thing in common: the client demanded more and more rich-client features at an ever increasing pace &#8211; without committing itself to real rich-client frameworks such as Flex or Silverlight. This leaves us with Javascript / AJAX for implementing highly dynamic User Interfaces for Web Applications. A very common problem when working with Ajax is the requirement to update multiple parts of a page in response to a single request. This post aims to familiarize the reader with my own approach to this problem.</p>
<p>At its core my solution consists of just two functions &#8211; one running server side and the other executing on the client. The first function is intended to run on the server and is written in Groovy. It was originally written in Python for use with the <a href="http://djangoproject.com">Django</a> framework and I&#8217;ve ported it to Groovy when I switched to <a href="http://grails.org">Grails</a> as my primary RAD Web framework. This function takes a map as argument and returns a JSON encoded map where the key is a valid <a href="http://docs.jquery.com/Selectors">jQuery Selector </a> designating the targets for the update and the value is a map containing information how the matched elements should be modified and how the content for the update shall be produced. Don&#8217;t worry if you find this confusing at first. There&#8217;s a sample further down.</p>
<p><span id="more-39"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code32'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3932"><td class="code" id="p39code32"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">def</span> renderElementUpdateResponse<span style="color: #66cc66;">&#40;</span>elements<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">def</span> rendered_elements <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span>:<span style="color: #66cc66;">&#93;</span>
&nbsp;
  elements.<span style="color: #663399;">eachWithIndex</span>
  <span style="color: #66cc66;">&#123;</span> k, v, i <span style="color: #66cc66;">-&gt;</span>
    rendered_elements<span style="color: #66cc66;">&#91;</span>k<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span>:<span style="color: #66cc66;">&#93;</span>
    rendered_elements<span style="color: #66cc66;">&#91;</span>k<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'mode'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> v<span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'mode'</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// if content is a Map, feed it into g.render - using the key as template name and the value as model</span>
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #000000; font-weight: bold;">instanceof</span> java.<span style="color: #006600;">util</span>.<span style="color: #006600;">LinkedHashMap</span><span style="color: #66cc66;">&#41;</span>
      rendered_elements<span style="color: #66cc66;">&#91;</span>k<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> g.<span style="color: #006600;">render</span><span style="color: #66cc66;">&#40;</span>template: v<span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">keySet</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">toArray</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>, model: v<span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">values</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">toArray</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #b1b100;">else</span>
      rendered_elements<span style="color: #66cc66;">&#91;</span>k<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> v<span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'content'</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">def</span> tmp <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'updates'</span>: rendered_elements<span style="color: #66cc66;">&#93;</span>
  render tmp <span style="color: #000000; font-weight: bold;">as</span> JSON
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>The second function is written in Javascript and responsible for applying the JSON wrapped HTML fragments to their designated HTML DOM Elements:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code33'); return false;">View Code</a> JAVASCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3933"><td class="code" id="p39code33"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> applyElementUpdates<span style="color: #009900;">&#40;</span>transport<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> updates<span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>transport.<span style="color: #660066;">updates</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    updates <span style="color: #339933;">=</span> transport.<span style="color: #660066;">updates</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> scripts <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Array<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>  <span style="color: #006600; font-style: italic;">// need to queue initializers until all updates are done</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span>target <span style="color: #000066; font-weight: bold;">in</span> updates<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>updates<span style="color: #009900;">&#91;</span>target<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'mode'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'execute'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        code <span style="color: #339933;">=</span> updates<span style="color: #009900;">&#91;</span>target<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'content'</span><span style="color: #009900;">&#93;</span>
        scripts.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>code<span style="color: #009900;">&#41;</span>
        <span style="color: #000066; font-weight: bold;">continue</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #003366; font-weight: bold;">var</span> targetNode <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>target<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #003366; font-weight: bold;">var</span> newContent <span style="color: #339933;">=</span> updates<span style="color: #009900;">&#91;</span>target<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'content'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #003366; font-weight: bold;">var</span> oldContent <span style="color: #339933;">=</span> targetNode.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000066; font-weight: bold;">switch</span><span style="color: #009900;">&#40;</span>updates<span style="color: #009900;">&#91;</span>target<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'mode'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'replace'</span><span style="color: #339933;">:</span>
          targetNode.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>newContent<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'insert'</span><span style="color: #339933;">:</span>
          targetNode.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>newContent <span style="color: #339933;">+</span> oldContent<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'append'</span><span style="color: #339933;">:</span>
          targetNode.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>oldContent <span style="color: #339933;">+</span> newContent<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
          <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// now run initializers</span>
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span>i <span style="color: #000066; font-weight: bold;">in</span> scripts<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      code <span style="color: #339933;">=</span> scripts<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>
      <span style="color: #000066; font-weight: bold;">eval</span><span style="color: #009900;">&#40;</span>code<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>So how do you use it? Below you find all necessary code artifacts for implementing the described technique in arbitrary Grails application. Please note that this sample uses <a href="jquery.com">jQuery</a> for carrying out the actual AJAX request but it would be trivial to port this over to any other decent Javascript Framework like <a href="mootools.net">MooTools</a>, Prototype or YUI.<br />
<br/><br />
Let&#8217;s begin with the GSP page in <b>/views/test/index.gsp</b>:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code34'); return false;">View Code</a> ASP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3934"><td class="code" id="p39code34"><pre class="asp" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;%</span><span style="color: #006600; font-weight: bold;">@</span> page <span style="color: #330066;">contentType</span><span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;text/html;charset=UTF-8&quot;</span> <span style="color: #000000; font-weight: bold;">%&gt;</span>
<span style="color: #006600; font-weight: bold;">&lt;</span>html<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>head<span style="color: #006600; font-weight: bold;">&gt;</span>
    <span style="color: #006600; font-weight: bold;">&lt;</span>g<span style="color: #006600; font-weight: bold;">:</span>javascript src<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;jquery-1.3.2.js&quot;</span> <span style="color: #006600; font-weight: bold;">/&gt;</span>
    <span style="color: #006600; font-weight: bold;">&lt;</span>g<span style="color: #006600; font-weight: bold;">:</span>javascript src<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;applyElementUpdates.js&quot;</span> <span style="color: #006600; font-weight: bold;">/&gt;</span>
&nbsp;
    <span style="color: #006600; font-weight: bold;">&lt;</span>script type<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;text/javascript&quot;</span><span style="color: #006600; font-weight: bold;">&gt;</span>
    $<span style="color: #006600; font-weight:bold;">&#40;</span>document<span style="color: #006600; font-weight:bold;">&#41;</span>.<span style="color: #9900cc;">ready</span><span style="color: #006600; font-weight:bold;">&#40;</span><span style="color: #0000ff; font-weight: bold;">function</span><span style="color: #006600; font-weight:bold;">&#40;</span><span style="color: #006600; font-weight:bold;">&#41;</span>
    <span style="color: #006600; font-weight:bold;">&#123;</span>
      $<span style="color: #006600; font-weight:bold;">&#40;</span><span style="color: #008000;">'#btnClickMe').click(function()</span>
      <span style="color: #006600; font-weight:bold;">&#123;</span>
        $.<span style="color: #9900cc;">ajax</span><span style="color: #006600; font-weight:bold;">&#40;</span>
        <span style="color: #006600; font-weight:bold;">&#123;</span>
          url<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #008000;">'${createLink(controller: 'test', action: 'update')}',</span>
          type<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #cc0000;">&quot;POST&quot;</span>,
          dataType<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #cc0000;">&quot;json&quot;</span>,
          cache<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #0000ff; font-weight: bold;">false</span>,
          async<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #0000ff; font-weight: bold;">true</span>,
          success<span style="color: #006600; font-weight: bold;">:</span> <span style="color: #0000ff; font-weight: bold;">function</span><span style="color: #006600; font-weight:bold;">&#40;</span>data, <span style="color: #330066;">status</span><span style="color: #006600; font-weight:bold;">&#41;</span>
          <span style="color: #006600; font-weight:bold;">&#123;</span>
            applyElementUpdates<span style="color: #006600; font-weight:bold;">&#40;</span>data<span style="color: #006600; font-weight:bold;">&#41;</span>
          <span style="color: #006600; font-weight:bold;">&#125;</span>
        <span style="color: #006600; font-weight:bold;">&#125;</span><span style="color: #006600; font-weight:bold;">&#41;</span>
      <span style="color: #006600; font-weight:bold;">&#125;</span><span style="color: #006600; font-weight:bold;">&#41;</span>
    <span style="color: #006600; font-weight:bold;">&#125;</span><span style="color: #006600; font-weight:bold;">&#41;</span><span style="color: #006600; font-weight: bold;">;</span>
    <span style="color: #006600; font-weight: bold;">&lt;/</span>script<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;/</span>head<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>body<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>input type<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;button&quot;</span> id<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;btnClickMe&quot;</span> value<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;Click me&quot;</span><span style="color: #006600; font-weight: bold;">/&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>br<span style="color: #006600; font-weight: bold;">/&gt;&lt;</span>br<span style="color: #006600; font-weight: bold;">/&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>div id<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;div1&quot;</span><span style="color: #006600; font-weight: bold;">&gt;&lt;/</span>div<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;</span>div id<span style="color: #006600; font-weight: bold;">=</span><span style="color: #cc0000;">&quot;div2&quot;</span><span style="color: #006600; font-weight: bold;">&gt;&lt;/</span>div<span style="color: #006600; font-weight: bold;">&gt;</span>
  <span style="color: #006600; font-weight: bold;">&lt;/</span>body<span style="color: #006600; font-weight: bold;">&gt;</span>
<span style="color: #006600; font-weight: bold;">&lt;/</span>html<span style="color: #006600; font-weight: bold;">&gt;</span></pre></td></tr></table></div>

<p>The controller in <b>/controllers/TestController.groovy</b>:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code35'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3935"><td class="code" id="p39code35"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #a1a100;">grails.converters.JSON</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> TestController <span style="color: #000000; font-weight: bold;">extends</span> BaseController
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">def</span> index <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span>
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">def</span> update <span style="color: #66cc66;">=</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">def</span> model <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span>a: <span style="color: #cc66cc;">1</span>, b: <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// Note: renderElementUpdateResponse is supposed to be implemented in BaseController</span>
    <span style="color: #000000; font-weight: bold;">return</span> renderElementUpdateResponse<span style="color: #66cc66;">&#40;</span>
    <span style="color: #66cc66;">&#91;</span>
      <span style="color: #ff0000;">'#div1'</span>   : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'replace'</span>, <span style="color: #ff0000;">'content'</span> : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'fragment1'</span>: model <span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#93;</span>,
      <span style="color: #ff0000;">'#div2'</span>   : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'append'</span>, <span style="color: #ff0000;">'content'</span>  : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'fragment2'</span>: model <span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#93;</span>,
      <span style="color: #ff0000;">'__init__'</span>: <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'execute'</span>, <span style="color: #ff0000;">'content'</span> : <span style="color: #ff0000;">'alert(&quot;The page has been updated&quot;)'</span> <span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>The call to renderElementUpdateResponse needs some explanation. Let&#8217;s step through the arguments line by line.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code36'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3936"><td class="code" id="p39code36"><pre class="groovy" style="font-family:monospace;"> <span style="color: #ff0000;">'#div1'</span>: <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'replace'</span>, <span style="color: #ff0000;">'content'</span> : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'fragment1'</span>: model <span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#93;</span></pre></td></tr></table></div>

<p><i>&#8220;[ 'fragment1': model ] ]&#8221;</i> is the only relevant part on the server side. It means &#8220;render the GSP template /views/test/_fragment1.gsp, pass it the variable model as the model and store the resulting string as the content for the update. On the client side it tells the applyElementUpdates() function to replace <i>(mode: replace)</i> the output for this line in all elements with id=&#8221;div1&#8243;.<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code37'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3937"><td class="code" id="p39code37"><pre class="groovy" style="font-family:monospace;"> <span style="color: #ff0000;">'#div2'</span>: <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'append'</span>, <span style="color: #ff0000;">'content'</span> : <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'fragment2'</span>: model <span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#93;</span></pre></td></tr></table></div>

<p>Works basically the same as the previous line only that id=&#8221;div2&#8243; is targetted and rendering /views/test/_fragment2.gsp will produce the content which is going to be appended to the target element rather than replacing it.<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code38'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3938"><td class="code" id="p39code38"><pre class="groovy" style="font-family:monospace;"> <span style="color: #ff0000;">'__init__'</span>: <span style="color: #66cc66;">&#91;</span> <span style="color: #ff0000;">'mode'</span>: <span style="color: #ff0000;">'execute'</span>, <span style="color: #ff0000;">'content'</span> : <span style="color: #ff0000;">'alert(&quot;The page has been updated&quot;)'</span> <span style="color: #66cc66;">&#93;</span></pre></td></tr></table></div>

<p>In addition to updating DOM elements we can also send code to the client which is run <b>after</b> all elements have been updated. Such fragments are called initializers and are identified on the client by their mode attribute which must be &#8216;execute&#8217;. This sample also demonstrates that fragment content can be specifed directly (<i>alert(&#8220;The page has been updated&#8221;)</i>) instead of being produced by rendering a template. Please note that the selector (&#8216;__init__&#8217;) is unused in this case. The sole reason for chosing that id was to emphasize the purpose of this fragment.<br />
<br/></p>
<p>The final missing bits are the aforementioned Grails templates which are going to producing the content for the updated elements. </p>
<p>The fragment for updating the first div in <b>/views/test/_fragment1.gsp</b>:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code39'); return false;">View Code</a> ASP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3939"><td class="code" id="p39code39"><pre class="asp" style="font-family:monospace;"><span style="color: #006600; font-weight: bold;">&lt;</span>span<span style="color: #006600; font-weight: bold;">&gt;</span>Value of A <span style="color: #990099; font-weight: bold;">is</span> $<span style="color: #006600; font-weight:bold;">&#123;</span>a<span style="color: #006600; font-weight:bold;">&#125;</span><span style="color: #006600; font-weight: bold;">&lt;/</span>span<span style="color: #006600; font-weight: bold;">&gt;</span></pre></td></tr></table></div>

<p>The fragment for updating the second div in <b>/views/test/_fragment2.gsp</b>:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p39code40'); return false;">View Code</a> ASP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3940"><td class="code" id="p39code40"><pre class="asp" style="font-family:monospace;"><span style="color: #006600; font-weight: bold;">&lt;</span>span<span style="color: #006600; font-weight: bold;">&gt;</span>Value of B <span style="color: #990099; font-weight: bold;">is</span> $<span style="color: #006600; font-weight:bold;">&#123;</span>b<span style="color: #006600; font-weight:bold;">&#125;</span><span style="color: #006600; font-weight: bold;">&lt;/</span>span<span style="color: #006600; font-weight: bold;">&gt;&lt;</span>br<span style="color: #006600; font-weight: bold;">/&gt;</span></pre></td></tr></table></div>

<p>Finally, opening the example page on your browser and clicking the button results in the following actions:</p>
<ul>
<li>The div1 element gets updated with the HTML output of rendering /views/test/_fragment1.gsp against the simple model. The contents of div1 are replaced</li>
<li>The div2 element gets updated with the HTML output of rendering /views/test/_fragment2.gsp against the simple model. The HTML is appended to the div rather then replacing the contents.</li>
<li>An alert box is displayed</li>
</ul>
<p>That&#8217;s it folks. I hope you found this post useful. </p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=39&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/07/20/updating-multiple-page-fragments-with-grails-and-ajax/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Using GIT with Grails UI-Performance Plugin</title>
		<link>http://weichhold.com/2009/06/18/using-git-with-grails-ui-performance-plugin/</link>
		<comments>http://weichhold.com/2009/06/18/using-git-with-grails-ui-performance-plugin/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 18:16:53 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=36</guid>
		<description><![CDATA[I&#8217;ve been doing a serious amount of Grails Development lately and if there&#8217;s one Grails Plugin I consider mandatory for any serious production deployment then it is the UI-Performance plugin by Burt Beckwith. One of the features of the plugin that reduces server load is versioning and far-future &#8220;Expires&#8221; and &#8220;Cache-Control&#8221; headers for static resources. Each time [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing a serious amount of Grails Development lately and if there&#8217;s one Grails Plugin I consider mandatory for any serious production deployment then it is the <a href="http://grails.org/plugin/ui-performance" target="_blank">UI-Performance plugin</a> by Burt Beckwith. One of the features of the plugin that reduces server load is versioning and far-future &#8220;Expires&#8221; and &#8220;Cache-Control&#8221; headers for static resources.</p>
<p>Each time you generate a new WAR for deployment, a new version is applied to all image, .js, and .css files so files can be cached forever. The next time you deploy a new version of your application, all of the resource file names will have changed, so only then will files be requested. The default process for determining the version is to look at the version of the root project folder in the Subversion metadata files. Since I&#8217;ve switched to <a href="http://git-scm.com/">GIT</a> for all my projects a while ago the plugin would fallback to <em>&#8220;System.currentTimeMillis().toString()&#8221; </em>to compute the version.</p>
<p>My solution is to include the following line in my projects Config.groovy:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p36code42'); return false;">View Code</a> GROOVY</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p3642"><td class="code" id="p36code42"><pre class="groovy" style="font-family:monospace;">uiperformance.<span style="color: #006600;">determineVersion</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #66cc66;">-&gt;</span> <span style="color: #ff0000;">&quot;git rev-list --max-count=1 HEAD&quot;</span>.<span style="color: #993399; font-weight: bold;">execute</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">text</span>.<span style="color: #006600;">trim</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>This allows the HEAD commit SHA1 hash of the current branch to be used as the uiperformance version for deployment.</p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=36&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/06/18/using-git-with-grails-ui-performance-plugin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>VirtualPC images with Windows XP and IE</title>
		<link>http://weichhold.com/2009/02/18/virtual-xp-images-with-windows-xp-and-ie/</link>
		<comments>http://weichhold.com/2009/02/18/virtual-xp-images-with-windows-xp-and-ie/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 01:05:47 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[VirtualPC]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=29</guid>
		<description><![CDATA[This is one of the very rare occasions where Microsoft actually did something cool. A couple days ago I needed to test one of my web apps with Internet Explorer 8 and just for giggles with IE6 &#8211; although we&#8217;ve dropped support for that dinosaur a while ago. Remembering my previous experience with IE8 and [...]]]></description>
			<content:encoded><![CDATA[<p>This is one of the very rare occasions where Microsoft actually did something cool. A couple days ago I needed to test one of my web apps with Internet Explorer 8 and just for giggles with IE6 &#8211; although we&#8217;ve dropped support for that dinosaur a while ago. Remembering my previous experience with IE8 and my inability to go back to 7 all too well &#8211; yes don&#8217;t laugh at me, I should have known better I know &#8211; I was preparing to fire up VMWare and create two XP Images, one for each browser version. But imagine my surprise when I discovered that Microsoft actually offers pre-configured ready to launch Windows XP VirtualPC Images for every possible IE version for free.</p>
<p>Be advised that these images expire in a couple of months but Microsoft seems to make new images  available shortly before the old ones expire.</p>
<p>Here&#8217;s the link: <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7c2b5317-a40f-4e86-8835-d37170c5923e&amp;displaylang=en">http://www.microsoft.com/downloads/details.aspx?FamilyID=7c2b5317-a40f-4e86-8835-d37170c5923e&amp;displaylang=en</a></p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=29&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/02/18/virtual-xp-images-with-windows-xp-and-ie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>High Performance Media Merging with Django, Nginx and Memcached</title>
		<link>http://weichhold.com/2009/02/16/high-performance-media-merging-with-django-nginx-and-memcached/</link>
		<comments>http://weichhold.com/2009/02/16/high-performance-media-merging-with-django-nginx-and-memcached/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 00:20:30 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=18</guid>
		<description><![CDATA[I admit it &#8211; I&#8217;m a performance junkie. I can&#8217;t stand code that just works but performs poorly. Being said, I recently fell in love with Django (a fantastic Python powered web application framework). In one of my current projects &#8211; xarmory.com &#8211; the number of requests for static resources issued during page load began [...]]]></description>
			<content:encoded><![CDATA[<p>I admit it &#8211; I&#8217;m a performance junkie. I can&#8217;t stand code that just works but performs poorly. Being said, I recently fell in love with Django (a fantastic Python powered web application framework). In one of my current projects &#8211; <a href="http://xarmory.com">xarmory.com</a> &#8211; the number of requests for static resources issued during page load began to bother me. The project makes intensive use of jQuery and it&#8217;s my personal belief that Django + jQuery is a match made in heaven. When working with jQuery you will find yourself often in the situation to rely in cool little jQuery plugins &#8211; each distributed as a seperate javascript file of course. When a project grows, those files begin to add up. In the case of xarmory.com we now had eleven javascript references in the header section of the page. Although the individual files are were only 3-11k in Size, the request overhead for all those tiny files became unacceptably in my eyes.</p>
<p>To alleviate the problem I decided to resort to a simple solution and just merge the individual script files into a single file. A pretty common practice. Before reinventing the wheel I surfed the net for existing solutions and found two which I gave a shot. Short story, both solutions had their share of problems mostly stemming from the fact that they wanted to do it all and integrate their own Javascript Minifier in addition to the merging. During my short evaluation both Minifiers choked on fifty percent of my javascript files, even on the official jquery 1.2.6 script. A bit frustrated I decided to roll out my own Django Template Tag based on this <a href="http://www.djangosnippets.org/snippets/405/">code</a>.</p>
<p><span id="more-18"></span><br />
I can be used like this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p18code48'); return false;">View Code</a> PYTHON</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1848"><td class="code" id="p18code48"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#123;</span><span style="color: #66cc66;">%</span> load mediamerge <span style="color: #66cc66;">%</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: black;">&#123;</span><span style="color: #66cc66;">%</span> mediamerge merged/standard <span style="color: #ff4500;">1</span> scripts/jquery-1.2.6.<span style="color: #008000;">min</span>.<span style="color: black;">js</span> scripts/jquery.<span style="color: black;">cookie</span>.<span style="color: black;">js</span> scripts/superfish.<span style="color: black;">js</span> scripts/supersubs.<span style="color: black;">js</span> scripts/shared.<span style="color: black;">js</span> <span style="color: #66cc66;">%</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>The first line obviously makes the mediamerge tag available to the template. The second line needs more explanation. The first parameter has two meanings</p>
<ul>
<li>First it is the relative path of the generated merged javascript file. The path is relativ to settings.MEDIA_ROOT (not used if the mediamerged is configured to use memcached &#8211; on to that later)</li>
<li>Second it defines an URI relative to settings.MEDIA_URL</li>
</ul>
<p>The second parameter defines a numeric version of the merged scripts and needs to be bumped by you whenever one of the files changes.</p>
<p>After the version follows the list of resources to be merged. All specified relative to settings.MEDIA_ROOT.</p>
<p>Assuming that settings.MEDIA_URL = http://static.example.com/ the tag above would result in the following HTML:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p18code49'); return false;">View Code</a> HTML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1849"><td class="code" id="p18code49"><pre class="html" style="font-family:monospace;">&lt;script src=&quot;http://static.example.com/merged/standard.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;!--mce:0--&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>Great, we&#8217;ve cut the number of requests by a factor. But it gets even faster. The mediamerge tag can be instructed to not generate an output file but to put the merged content directly into memcached (I&#8217;m obsessed with memcached) for a webserver supporting memcached to pick it up there. Nginx does and it is lightning fast serving static content.</p>
<p>So we instruct the mediamerge tag to use memcached in settings.py:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p18code50'); return false;">View Code</a> PYTHON</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1850"><td class="code" id="p18code50"><pre class="python" style="font-family:monospace;">MEDIAMERGE_ENABLE_MEMCACHED = <span style="color: #008000;">True</span>
MEDIAMERGE_MEMCACHED_URI_PREFIX = <span style="color: #483d8b;">&quot;mmerge_&quot;</span>
MEMCACHED_SERVERS = <span style="color: black;">&#91;</span> <span style="color: #483d8b;">'localhost:11211'</span> <span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Using these settings, mediamerge will store the merged scripts in memcached under the key &#8216;mmerge_ http://static.example.com/merged/standard.js?1&#8242; (settings.MEDIAMERGE_MEMCACHED_URI_PREFIX + settings.MEDIA_URL + )</p>
<p>The final thing to make it all work is to instruct Nginx to pick up request for resources handled by the mediamerge tag directly from memcached.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p18code51'); return false;">View Code</a> APACHE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1851"><td class="code" id="p18code51"><pre class="apache" style="font-family:monospace;">server
{
	<span style="color: #00007f;">listen</span> <span style="color: #ff0000;">80</span>;
	server_name static.example.com;
	expires 24h;
&nbsp;
	<span style="color: #adadad; font-style: italic;"># mediamerge</span>
	location /merged/
	{
		set $memcached_key mmerge_$scheme://$server_name$request_uri;
		memcached_pass 127.0.0.1:<span style="color: #ff0000;">11211</span>;
	}
&nbsp;
	location /
	{
		root /var/www/example_static;
	}
}</pre></td></tr></table></div>

<p>Bingo, Nginx will now serve all requests for resources in http://static.example.com /merged/ by looking up the contents in the specified memcached server (cluster). Nginx is already very fast for traditionally served static files but this is just ridiculously fast.</p>
<p><strong>UPDATE:</strong> I&#8217;ve updated the source below since the article was originally posted. Changes: </p>
<ul>
<li>A new option is now supported when using the disk based method: MEDIAMERGE_DISABLE_MERGE_UPDATES. Setting this option to True in settings.py will disable any checks for updated merge source files and is intended for production servers where your input files should not change in the background unless the web server is restarted. This should improve the rendering time of the tag in production considerably.</li>
<li>The files are now opened and written in binary mode</li>
</ul>
<p>Here&#8217;s the source code for the mediamerge template tag:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p18code52'); return false;">View Code</a> PYTHON</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1852"><td class="code" id="p18code52"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span> <span style="color: #ff7700;font-weight:bold;">import</span> path
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">cStringIO</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: #dc143c;">StringIO</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span> <span style="color: #ff7700;font-weight:bold;">import</span> Library, Node, TemplateSyntaxError
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'mediamerge'</span><span style="color: black;">&#41;</span>
mc = <span style="color: #008000;">None</span>
register = Library<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> JSMergeNode<span style="color: black;">&#40;</span>Node<span style="color: black;">&#41;</span>:
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, js_name, js_ver, js_files<span style="color: black;">&#41;</span>:
		<span style="color: #008000;">self</span>.<span style="color: black;">js_name</span> = <span style="color: #483d8b;">'%s.js'</span> <span style="color: #66cc66;">%</span> js_name
		<span style="color: #008000;">self</span>.<span style="color: black;">js_ver</span> = js_ver
		<span style="color: #008000;">self</span>.<span style="color: black;">js_files</span> = js_files
		<span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span> = path.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span>path.<span style="color: black;">join</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_ROOT</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># make sure that the target directory exists</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> settings.<span style="color: black;">MEDIAMERGE_ENABLE_MEMCACHED</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> path.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>path.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
			<span style="color: #dc143c;">os</span>.<span style="color: black;">makedirs</span><span style="color: black;">&#40;</span>path.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> merge_files<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, merge_file<span style="color: black;">&#41;</span>:
		<span style="color: #808080; font-style: italic;"># join all input files into a single output file</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> js <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">js_files</span>:
			jspath = path.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span>path.<span style="color: black;">join</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_ROOT</span>, js<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
			<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> path.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>jspath<span style="color: black;">&#41;</span>:
				<span style="color: #ff7700;font-weight:bold;">continue</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">merge_js</span><span style="color: black;">&#40;</span>js, jspath, merge_file<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> render<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, context<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Implementation of the render method of the tag'</span><span style="color: #483d8b;">''</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">MEDIAMERGE_ENABLE_MEMCACHED</span>:
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">render_memcached</span><span style="color: black;">&#40;</span>context<span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">render_file</span><span style="color: black;">&#40;</span>context<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> render_passthrough<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, context<span style="color: black;">&#41;</span>:
		result = <span style="color: #483d8b;">&quot;&quot;</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> js <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">js_files</span>:
			<span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">MEDIA_URL</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'/'</span>:
				result += <span style="color: #483d8b;">'&lt;script type=&quot;text/javascript&quot; src=&quot;%s%s&quot;&gt;&lt;/script&gt;<span style="color: #000099; font-weight: bold;">\n</span>'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_URL</span>, js<span style="color: black;">&#41;</span>
			<span style="color: #ff7700;font-weight:bold;">else</span>:
				result += <span style="color: #483d8b;">'&lt;script type=&quot;text/javascript&quot; src=&quot;%s/%s&quot;&gt;&lt;/script&gt;<span style="color: #000099; font-weight: bold;">\n</span>'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_URL</span>, js<span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> result
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> render_memcached<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, context<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Memcached based render method - merged output directly stored in memcache - where nginx will pick it up based on the rquest uri) without using a temp file'</span><span style="color: #483d8b;">''</span>
		<span style="color: #ff7700;font-weight:bold;">import</span> memcache
		key = settings.<span style="color: black;">MEDIAMERGE_MEMCACHED_URI_PREFIX</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">compute_media_url</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">global</span> mc
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> mc:
			mc = memcache.<span style="color: black;">Client</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">MEMCACHED_SERVERS</span>, debug=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> mc.<span style="color: black;">get</span><span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>:
			merge_file = <span style="color: #dc143c;">StringIO</span>.<span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">merge_files</span><span style="color: black;">&#40;</span>merge_file<span style="color: black;">&#41;</span>
			contents = merge_file.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
			mc.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>key, contents, <span style="color: #ff4500;">3600</span><span style="color: black;">&#41;</span>
			logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Setting memcached value for for resource %s - key %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">js_name</span>, key<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			logger.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Merge key %s already exists in memcached for resource %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>key, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">js_tag</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> render_file<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, context<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">''</span><span style="color: #483d8b;">'File based render method - merged output directly stored in the file specified with the tag - relative to settings.MEDIA_ROOT'</span><span style="color: #483d8b;">''</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> path.<span style="color: black;">exists</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">self</span>.<span style="color: black;">is_merge_updated</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
			logger.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Trying to open output file %s for resource %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
			merge_file = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">merge_files</span><span style="color: black;">&#40;</span>merge_file<span style="color: black;">&#41;</span>
			merge_file.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			logger.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Merge file %s already exists for resource %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">js_tag</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> is_merge_updated<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">MEDIAMERGE_DISABLE_MERGE_UPDATES</span>:
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
		<span style="color: #483d8b;">&quot;&quot;&quot; compares modification time of all js with merged js &quot;&quot;&quot;</span>
		last_mtime = <span style="color: #ff4500;">0</span> <span style="color: #808080; font-style: italic;"># last modification time of a js file</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> js <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">js_files</span>:
			jspath = path.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span>path.<span style="color: black;">join</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_ROOT</span>, js<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
			jsstat = <span style="color: #dc143c;">os</span>.<span style="color: #dc143c;">stat</span><span style="color: black;">&#40;</span>jspath<span style="color: black;">&#41;</span>
			mtime = jsstat<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
			<span style="color: #ff7700;font-weight:bold;">if</span> last_mtime <span style="color: #66cc66;">&lt;</span> mtime:
				last_mtime = mtime
		merge_mtime = <span style="color: #dc143c;">os</span>.<span style="color: #dc143c;">stat</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">merge_filename</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span> merge_mtime <span style="color: #66cc66;">&gt;</span> last_mtime
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> merge_js<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, jsname, jspath, fd<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">&quot;&quot;&quot; do merging and compressing of javascript &quot;&quot;&quot;</span>
		logger.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Merging file %s for resource %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>jsname, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
		jsfile = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>jspath, <span style="color: #483d8b;">&quot;rb&quot;</span><span style="color: black;">&#41;</span>
		jscontent = jsfile.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		fd.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/* -- %s -- */<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>'</span> <span style="color: #66cc66;">%</span> jsname<span style="color: black;">&#41;</span>
		fd.<span style="color: black;">write</span><span style="color: black;">&#40;</span>jscontent<span style="color: black;">&#41;</span>
		fd.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> compute_media_url<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #808080; font-style: italic;"># detect if MEDIA_URL ends with a slash</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> settings.<span style="color: black;">MEDIA_URL</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'/'</span>:
			js_url = <span style="color: #483d8b;">'%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_URL</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_ver</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			js_url = <span style="color: #483d8b;">'%s/%s?%d'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>settings.<span style="color: black;">MEDIA_URL</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_name</span>, <span style="color: #008000;">self</span>.<span style="color: black;">js_ver</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span> js_url
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> js_tag<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">&quot;&quot;&quot; write js tag for merged file inclusion &quot;&quot;&quot;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'&lt;script type=&quot;text/javascript&quot; src=&quot;%s&quot;&gt;&lt;/script&gt;'</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">self</span>.<span style="color: black;">compute_media_url</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> do_jsmerge<span style="color: black;">&#40;</span><span style="color: #dc143c;">parser</span>, <span style="color: #dc143c;">token</span><span style="color: black;">&#41;</span>:
	<span style="color: #483d8b;">&quot;&quot;&quot;
	This will merge javascript files in only one compressed javascript.
&nbsp;
	Usage::
&nbsp;
		{% load mediamerge %}
		{% mediamerge &lt;output_js_file&gt; &lt;output_version_integer&gt; [jsfile1] [jsfile2] .. %}
&nbsp;
	Example::
&nbsp;
		{% load mediamerge %}
		{% mediamerge mediamergefile 1  js/file1.js js/file2.js js/file3.js %}
&nbsp;
	This will create (if not exists) a /media/mediamergefile.js with three files merged. The HTML output for this will be::
&nbsp;
		&lt;script type=&quot;text/javascript&quot; src=&quot;/media/mediamergefile.js&quot;&gt;&lt;/script&gt;
	&quot;&quot;&quot;</span>
	tokens = <span style="color: #dc143c;">token</span>.<span style="color: black;">contents</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>tokens<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">3</span>:
		<span style="color: #ff7700;font-weight:bold;">raise</span> TemplateSyntaxError<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;'%r' tag requires at least 1 arguments.&quot;</span> <span style="color: #66cc66;">%</span> tokens<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">return</span> JSMergeNode<span style="color: black;">&#40;</span>tokens<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>tokens<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, tokens<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
register.<span style="color: black;">tag</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'mediamerge'</span>, do_jsmerge<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<img src="http://weichhold.com/?ak_action=api_record_view&id=18&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2009/02/16/high-performance-media-merging-with-django-nginx-and-memcached/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>django, nginx, memcached &#8211; the dynamic trio</title>
		<link>http://weichhold.com/2008/09/12/django-nginx-memcached-the-dynamic-trio/</link>
		<comments>http://weichhold.com/2008/09/12/django-nginx-memcached-the-dynamic-trio/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 21:01:22 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=17</guid>
		<description><![CDATA[Inspired by this article I decided to find out if the same technique can be exploited in my current project which is developed in django. My first problem was to come up with a viable cache key scheme since simply using the full request URI as suggested in the article wouldn&#8217;t work for me because [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by <a href="http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/" target="_blank">this article</a> I decided to find out if the same technique can be exploited in my current project which is developed in <a href="http://www.djangoproject.com" target="_blank">django</a>.</p>
<p>My first problem was to come up with a viable cache key scheme since simply using the full request URI as suggested in the article wouldn&#8217;t work for me because my site renders a different version of a navigation menu depending on the authentication state of current the user. After weighing in the advantages and disadvantages between the super clean variant of factoring the session cookie and all other cookies into the <a href="http://www.danga.com/memcached/" target="_blank">memcached</a> key and a less heavy weight method that would only append a server supplied abstract &#8220;page version&#8221; field to the request URI, I went for the latter. My resulting nginx virtual host config was looking like this:</p>
<p><span id="more-17"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p17code56'); return false;">View Code</a> APACHE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1756"><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
37
38
39
40
41
</pre></td><td class="code" id="p17code56"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># define application servers</span>
upstream backend
{
  server 127.0.0.1:<span style="color: #ff0000;">8080</span> weight=<span style="color: #ff0000;">1</span>;
}
&nbsp;
server
{
  <span style="color: #00007f;">listen</span> <span style="color: #ff0000;">80</span>;
  server_name domain.com;
  access_log /var/log/nginx/domain.com.log;
&nbsp;
  location /
  {
    <span style="color: #adadad; font-style: italic;"># we never cache post requests</span>
    if ($request_method = POST)
    {
      proxy_pass http://backend;
      break;
    }
&nbsp;
    <span style="color: #adadad; font-style: italic;"># extract cache key args and compute cache key</span>
    if ($http_cookie ~* <span style="color: #7f007f;">&quot;pv=([^;]+)(?:;|$)&quot;</span>)
    {
      set $page_version $<span style="color: #ff0000;">1</span>;
    }
    set $memcached_key $request_uri&amp;amp;pv=$page_version;
&nbsp;
    <span style="color: #adadad; font-style: italic;"># Check if local memcached server can answer this request</span>
    default_type text/html;
    memcached_pass 127.0.0.1:<span style="color: #ff0000;">11211</span>;
&nbsp;
    <span style="color: #adadad; font-style: italic;"># Send to app. server if Memcached could not answer the request</span>
    error_page <span style="color: #ff0000;">404</span> = @cache_miss;
  }
&nbsp;
  location @cache_miss
  {
    proxy_pass http://backend;
  }
}</pre></td></tr></table></div>

<p>The important lines are line 23-27. Line 23 tests the cookies header of the current request for the presence of a cookie named &#8216;pv&#8217; using a regular expression and line 25 stores the extracted value of this cookie in a temporary variable. Later, in line 27 we combine the value of that variable with the request URI to form the final memcached key. For example if the request uri would be /foo and the headers would contain a cookie pv=acme123, then the cache key would be /foo&amp;pv=acme123.</p>
<p>Line 31 is where the actual memcached lookup happens. If the computed key is present in the cache, the cached page is returned immediately &#8211; completely bypassing the backend. If the page (or the specific version of the page) is not present in the cache, then the alternate branch at line 37 is taken which ultimately forwards the request to our load balanced cluster of application servers in line 39. The actual servers making up the cluster is defined at line 2. There&#8217;s currently only one lonely application server defined there and that&#8217;s a apache 2.2 listening on localhost port 8080 running our django application through mod_wsgi.</p>
<p>So far I have explained how the front line request processing in nginx works but how is invalidation handled? To tackle that problem I wrote a django middleware that can be applied to arbitrary django views using a decorator:<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p17code57'); return false;">View Code</a> PYTHON</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1757"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p17code57"><pre class="python" style="font-family:monospace;">@cache_page_nginx<span style="color: black;">&#40;</span><span style="color: #ff4500;">3600</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">6</span>, compute_common_page_version<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'index.html'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> compute_common_page_version<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
  <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'This method is called by the nginx_cache decorator
  The method is supposed to return some value that can be used to distinguish
  different cached versions of the same page. For now it is sufficient to differentiate
  between authenticated and anonymous users'</span><span style="color: #483d8b;">''</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> request.<span style="color: #dc143c;">user</span> <span style="color: #ff7700;font-weight:bold;">and</span> request.<span style="color: #dc143c;">user</span>.<span style="color: black;">is_authenticated</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>
  <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span></pre></td></tr></table></div>

<p>Some readers will notice that the decorator looks very similar to Django&#8217;s built-in cache_page decorator. And it actually works similar but with several important differences:</p>
<ul>
<li>It totally relies on nginx doing the actual cache lookup. The decorator is only responsible for storing the rendered content of page in the cache.</li>
<li>It bypasses the Django cache framework and talks to memcached directly using cmemcached or python-memcached. This was done because there&#8217;s reallly no point in supporting an additional level of abstraction if the consumer of the cached content won&#8217;t look for it anywhere but in memcached.</li>
</ul>
<p>A word about the compute_common_page_version function. What does it do? The purpose of this method is to ensure that the cache will contain at maximum two distinct versions of the home page. Once for authenticated users and one for anonymous users. For more complex scenarios, the complexity of this method would also increase, resulting on more distinct versions of the same page. Obviously the difficulty lies in maintaining data integrity for every user while not producing to many cached versions of a page, thus increasing memory pressure on the server and lowering cache hit ratio.<br />
<br/><br />
The decorator:<br />
<br/></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p17code58'); return false;">View Code</a> PYTHON</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1758"><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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
</pre></td><td class="code" id="p17code58"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">decorators</span> <span style="color: #ff7700;font-weight:bold;">import</span> decorator_from_middleware
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span> <span style="color: #ff7700;font-weight:bold;">import</span> cache
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">encoding</span> <span style="color: #ff7700;font-weight:bold;">import</span> smart_unicode, smart_str
<span style="color: #ff7700;font-weight:bold;">from</span> utils <span style="color: #ff7700;font-weight:bold;">import</span> kdebug
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> cmemcache <span style="color: #ff7700;font-weight:bold;">as</span> memcache
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">import</span> memcache
    <span style="color: #ff7700;font-weight:bold;">except</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> InvalidCacheBackendError<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Memcached cache backend requires either the 'memcache' or 'cmemcache' library&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> UpdateCacheMiddleware<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  <span style="color: #483d8b;">&quot;&quot;&quot;
  Updates memcached with the response of the request. It is of _paramount_
  importance that the generated cache_key matches exactly the key generated
  by your web to lookup the page from the cache.
&nbsp;
  This class talks to memcached, bypassing Djangos cache backend because
  it is only meant to talk to memcached and nothing else.
&nbsp;
  Must the first piece of middleware in settings.MIDDLEWARE_CLASSES so
  that it'll get called last during the response phase.
  &quot;&quot;&quot;</span>
  <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, cache_timeout, page_version_method<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'timeout - is the timeout in seconds after which the cached response expires in memcached
    page_version_method - is called during response processing and must return an arbitrary value
    that can be used to distinguish different cached versions of the same page '</span><span style="color: #483d8b;">''</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">cache_timeout</span> = cache_timeout
    <span style="color: #008000;">self</span>.<span style="color: black;">page_version_method</span> = page_version_method
    <span style="color: #008000;">self</span>.<span style="color: black;">cache</span> = memcache.<span style="color: black;">Client</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">NGINX_MEMCACHED_SERVERS</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">cookie_name</span> = <span style="color: #483d8b;">'pv'</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> process_response<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, response<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Sets the cache, if needed.&quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> settings.<span style="color: black;">NGINX_MEMCACHED_ENABLE</span> <span style="color: #ff7700;font-weight:bold;">or</span> request.<span style="color: black;">method</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'GET'</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff7700;font-weight:bold;">not</span> response.<span style="color: black;">status_code</span> == <span style="color: #ff4500;">200</span>:
      <span style="color: #808080; font-style: italic;"># because of interactions between this middleware and the</span>
      <span style="color: #808080; font-style: italic;"># HTTPMiddleware, which throws the body of a HEAD-request</span>
      <span style="color: #808080; font-style: italic;"># away before this middleware gets a chance to cache it.</span>
      <span style="color: #ff7700;font-weight:bold;">return</span> response
&nbsp;
    <span style="color: #008000;">self</span>.<span style="color: black;">cache_response</span><span style="color: black;">&#40;</span>request, response<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> response
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> cache_response<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, response<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Manually insertion of cached version of page into the cache'</span><span style="color: #483d8b;">''</span>
    <span style="color: #808080; font-style: italic;"># retrieve page version</span>
    pv = <span style="color: #008000;">self</span>.<span style="color: black;">page_version_method</span><span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># compute key that's follows the same naming convention as specified in nginx configuration:</span>
    <span style="color: #808080; font-style: italic;"># set $memcached_key $request_uri&amp;sid=$session_id;</span>
    cache_key = <span style="color: #008000;">self</span>.<span style="color: black;">compute_cache_key_from_request</span><span style="color: black;">&#40;</span>request, pv<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># update cache</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">cache</span>.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>cache_key, response._get_content<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">cache_timeout</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># communicate the page version to the browser using cookie</span>
    response.<span style="color: black;">set_cookie</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cookie_name</span>, pv<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> compute_cache_key_from_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, page_version<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Computes the cache key for the specified page and version of the page'</span><span style="color: #483d8b;">''</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">compute_cache_key</span><span style="color: black;">&#40;</span>request.<span style="color: black;">get_full_path</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, page_version<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> compute_cache_key<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, page, page_version<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Computes the cache key for the specified page and version of the page'</span><span style="color: #483d8b;">''</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> smart_str<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s&amp;%s=%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>page, <span style="color: #008000;">self</span>.<span style="color: black;">cookie_name</span>, page_version<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> invalidate_page_version_from_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, page_version<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Removes the specified version of the page requested by '</span>request<span style="color: #483d8b;">' from the cache'</span><span style="color: #483d8b;">''</span>
    cache_key = <span style="color: #008000;">self</span>.<span style="color: black;">compute_cache_key_from_request</span><span style="color: black;">&#40;</span>request, page_version<span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">cache</span>.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>cache_key<span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #ff7700;font-weight:bold;">def</span> invalidate_page_version<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, page, page_version<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'Removes the specified version of the page requested by '</span>request<span style="color: #483d8b;">' from the cache'</span><span style="color: #483d8b;">''</span>
    cache_key = <span style="color: #008000;">self</span>.<span style="color: black;">compute_cache_key</span><span style="color: black;">&#40;</span>request, page_version<span style="color: black;">&#41;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">cache</span>.<span style="color: black;">delete</span><span style="color: black;">&#40;</span>cache_key<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># decorator</span>
cache_page_nginx = decorator_from_middleware<span style="color: black;">&#40;</span>UpdateCacheMiddleware<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<img src="http://weichhold.com/?ak_action=api_record_view&id=17&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2008/09/12/django-nginx-memcached-the-dynamic-trio/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using IntelliJ for Django Development</title>
		<link>http://weichhold.com/2008/07/11/using-intellij-for-django-development/</link>
		<comments>http://weichhold.com/2008/07/11/using-intellij-for-django-development/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 10:08:56 +0000</pubDate>
		<dc:creator>oliver</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Hosting]]></category>
		<category><![CDATA[IntelliJ]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Notepad++]]></category>

		<guid isPermaLink="false">http://weichhold.com/?p=15</guid>
		<description><![CDATA[About a year ago I’ve switched over to IntelliJ as my primary Java IDE. When I began to dabble a bit in Django a few days ago, I realized that IntelliJ had me spoiled when it comes to Editor Features – especially when working with Javascript and HTML files. Notepad++ &#8211; although a great text [...]]]></description>
			<content:encoded><![CDATA[<p>About a year ago I’ve switched over to IntelliJ as my primary Java IDE. When I began to dabble a bit in Django a few days ago, I realized that IntelliJ had me spoiled when it comes to Editor Features – especially when working with Javascript and HTML files. Notepad++ &#8211; although a great text editor on its own right &#8211; simply didn’t cut it for me for web development.</p>
<p>When I tried opening my Django files in IntelliJ I had to realize that IntelliJ needs a project context for opening a file. Even for a simple html file. Fortunately the solution was pretty straight forward. Navigate to your Django project root directory and create a new file .project. Some of you have guessed it: we are pretending to be Eclipse. Open the file in a text editor and paste the following snipped into it:</p>
<blockquote><p>&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;projectDescription&gt;<br />
&lt;name&gt;myproject&lt;/name&gt;<br />
&lt;comment&gt;&lt;/comment&gt;<br />
&lt;projects&gt;&lt;/projects&gt;<br />
&lt;/projectDescription&gt;</p></blockquote>
<p>Edit the &lt;name&gt; tag value and change it to your liking.</p>
<p><span id="more-15"></span></p>
<p>Now it’s time to launch IntelliJ. Select <em>File </em>-&gt; <em>New Project</em>. Select <em>Import project from external model</em> and click <em>Next</em>. Select <em>Eclipse </em>(should be the default) and click <em>Next</em>. Now enter the path to your Django project root folder in the <em>Select Eclipse projects directory</em> field. Click <em>Next</em>. You should now see the name of your pseudo eclipse project in the list. Click <em>Next</em>. You may now change the project name or just click <em>Finish</em>.  Open the project view and change to <em>Project </em>mode. Congratulations, you have imported your Django project into IntelliJ.</p>
<p>I&#8217;d suggest that you install the Pythonid plugin for IntelliJ in order to get a better Python code editing experience and that you add .pyc and .pyo to the <em>Ignored files and folders </em>in IntelliJ&#8217;s <em>General Settings</em> as final steps.</p>
<img src="http://weichhold.com/?ak_action=api_record_view&id=15&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://weichhold.com/2008/07/11/using-intellij-for-django-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
