<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-4919603745642637061</atom:id><lastBuildDate>Fri, 25 Oct 2024 10:37:45 +0000</lastBuildDate><category>grails</category><category>groovy</category><category>gorm</category><category>testing</category><category>Front-end</category><category>selenium</category><category>CSS</category><category>HTML</category><category>controllers</category><category>hibernate</category><category>forms</category><category>unit testing</category><category>F5</category><category>binding</category><category>build</category><category>caching</category><category>command objects</category><category>domain objects</category><category>javascript</category><category>oop</category><category>simplicity</category><category>taglibs</category><category>Debugging</category><category>Proxy</category><category>UI Design</category><category>annotations</category><category>design</category><category>enums</category><category>gant</category><category>gmock</category><category>grails 1.1</category><category>grails-plugin</category><category>intellij</category><category>linux</category><category>liquibase</category><category>metaclass</category><category>mocking</category><category>plugins</category><category>productivity</category><category>services</category><category>sitemesh</category><category>subversion intellij</category><category>validation</category><category>Fast Cache</category><category>HSQLDB</category><category>IE</category><category>Postgres</category><category>SEO</category><category>XHTML</category><category>Zeus</category><category>ajax</category><category>architecture</category><category>bash</category><category>books</category><category>builders</category><category>categories</category><category>compression</category><category>data migration</category><category>diff</category><category>disk</category><category>exceptions</category><category>fun</category><category>gpath</category><category>grails source</category><category>gsp</category><category>gstring</category><category>hamcrest</category><category>handy</category><category>hints</category><category>httpunit</category><category>iRules</category><category>inheritance</category><category>invalidation triggers</category><category>joda time</category><category>layout</category><category>library</category><category>mac osx java</category><category>manytomany</category><category>map</category><category>markupbuilder</category><category>noise</category><category>ood</category><category>openvz</category><category>refactoring</category><category>searchable</category><category>selenium-ide</category><category>spock</category><category>spring</category><category>string</category><category>subshell</category><category>tdd</category><category>team</category><category>test design</category><category>timing</category><category>too many open files</category><category>tutorial</category><category>ulimit</category><category>url mapping</category><category>virtualization</category><category>webtest</category><category>xpath</category><title>STATE YOUR BIZNESS</title><description>ma bizness is groovy grails</description><link>http://stateyourbizness.blogspot.com/</link><managingEditor>noreply@blogger.com (Simon Baker)</managingEditor><generator>Blogger</generator><openSearch:totalResults>129</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8432815583441683721</guid><pubDate>Sat, 28 Jul 2012 19:04:00 +0000</pubDate><atom:updated>2012-07-28T20:04:37.587+01:00</atom:updated><title>Viewing Liquibase&#39;s Generated Changelog At Runtime</title><description>I know grails 2.x has a migrations plugin, but if you still using / prefer the liquibase one then read on...&lt;br /&gt;
&lt;br /&gt;
I
 use liquibase in all environments &quot;north&quot; of development to manage the 
database schema and reference data, but still use create-drop while 
developing locally. It can be a pain to construct changesets by hand, 
but it&#39;s also awkward to run grails generate-changelog (especially if 
development normally uses an in memory database).&amp;nbsp; Much better if you 
could see the generated changelog while the application is running. 
Here&#39;s how...&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;import liquibase.database.*&lt;br /&gt;import liquibase.diff.*&lt;br /&gt;import java.sql.Connection&lt;br /&gt;&lt;br /&gt;class LiquibaseController {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def dataSource&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def index() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Connection connection = dataSource.connection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DatabaseFactory factory = DatabaseFactory.getInstance()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Database database = factory.findCorrectDatabaseImplementation(connection)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; database.setDefaultSchemaName(&#39;schemaName&#39;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Diff diff = new Diff(database, &#39;schemaName&#39;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DiffResult diffResult = diff.compare()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; diffResult.printChangeLog(new PrintStream(response.outputStream), database)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; response.contentType = &#39;text/xml&#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; response.outputStream.flush()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
S.</description><link>http://stateyourbizness.blogspot.com/2012/07/viewing-liquibases-generated-changelog.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8867228670661612577</guid><pubDate>Thu, 07 Apr 2011 21:47:00 +0000</pubDate><atom:updated>2011-04-07T23:04:38.110+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">books</category><category domain="http://www.blogger.com/atom/ns#">library</category><title>Techie Books Suggestions</title><description>&lt;div&gt;&lt;p&gt;(Or &quot;How I Learned To Stop Worrying About Gramatically Correct Blog Titles&quot;)&lt;/p&gt;
&lt;p&gt;I&#39;m starting to add to the dev side of my techie library which, as you can appreciate, is pretty biased toward sysadmin stuff at the moment (DNS, firewall, exim, Jabber and so on).&lt;/p&gt;
&lt;p&gt;So far I&#39;ve added the two GinAs, and recently jQuery in Action, Javascript: The Good Bits, Javascript: The Definitive Guide and The Java Developer&#39;s Guide to Eclipse.&lt;/p&gt;
&lt;p&gt;So what else should I have on my wish list? Freely downloadable is good too - it doesn&#39;t have to be expensive dead-tree format - especially if it can be Kindleised.&lt;/p&gt;
&lt;p&gt;Would love to hear your thoughts and suggestions.&lt;/p&gt;
&lt;/div&gt;</description><link>http://stateyourbizness.blogspot.com/2011/04/techie-books-suggestions.html</link><author>noreply@blogger.com (Darren)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-7806174462674488566</guid><pubDate>Tue, 22 Feb 2011 13:11:00 +0000</pubDate><atom:updated>2011-02-23T13:49:33.275+00:00</atom:updated><title>Remote Controlled Geb Functional Tests</title><description>I&#39;ve just started on a new project where Geb and Spock are our main functional testing tools. They&#39;re nice tools to work with but sometimes it&#39;s hard to write tests quickly when you can&#39;t see what&#39;s going on. I want to be able to step through tests like in Selenium IDE but without all the shortcomings of using fixture controllers.&lt;br /&gt;&lt;br /&gt;One way to develop functional tests under Grails is to keep the app running while you launch tests from another jvm and use -baseUrl to target the remote jvm. You can do this from the command line or use the Functional Test Development plugin. Another way is to keep the app running and run the tests from within an IDE like IntelliJ; a bonus is that you can run individual tests/features which is great if you have a fairly large spec.&lt;br /&gt;&lt;br /&gt;Whichever way you choose, you&#39;re going to need to setup data on the target jvm. On my last project we used fixture controllers that we would call from our functional tests but these grew into thousands of lines because re-use after a while became difficult. A better way to do it is to bundle the test data with the actual test which is what the Remote Control plugin allows us to do - the plugin documentation has a better explanation of what I mean.&lt;br /&gt;&lt;br /&gt;With all that said, what I want to be able to do is:&lt;ul&gt;    &lt;li&gt;Run my app up&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Create my data in my setup block as though I was in an integration test.&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;Right click on the test from intellij and hit run (or use debug and step through line by line)&lt;/li&gt;&lt;/ul&gt;Take a look at the plugin docs, it&#39;s pretty straight forward but we had to override getBaseUrl and create our own BuildSettingsHolder because remote control doesn&#39;t like running outside of a grails command line. So our parent Spec looked like:&lt;br /&gt;&lt;pre&gt;public ParentSpec extends GebSpec {&lt;br /&gt;  String getBaseUrl() {&lt;br /&gt;       &quot;http://localhost:8080/monkeytails/&quot;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;   def setupSpec() {&lt;br /&gt;&lt;br /&gt;       if (BuildSettingsHolder.getSettings() == null) {&lt;br /&gt;           BuildSettings bs = new BuildSettings()&lt;br /&gt;           bs.metaClass.getFunctionalTestBaseUrl = { getBaseUrl() }&lt;br /&gt;&lt;br /&gt;           BuildSettingsHolder.setSettings(bs)&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def cleanupSpec() {&lt;br /&gt;       resetDatabase()&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   void resetDatabase() {&lt;br /&gt;       def remote = new RemoteControl()&lt;br /&gt;       remote {&lt;br /&gt;           User.list().each{ it.delete(flush:true) }&lt;br /&gt;           // Other teardown stuff goes here&lt;br /&gt;           // ...&lt;br /&gt;           return true&lt;br /&gt;       }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;and then your tests:&lt;br /&gt;&lt;pre&gt;    def &quot;Test something&quot;() {&lt;br /&gt;&lt;br /&gt;      setup:&lt;br /&gt;          def remote = new RemoteControl()&lt;br /&gt;          remote {&lt;br /&gt;              User user = new User()&lt;br /&gt;              user.save(flush: true)&lt;br /&gt;              return true //have to return something serializable&lt;br /&gt;          }&lt;br /&gt;      .&lt;br /&gt;      .&lt;br /&gt;  }&lt;/pre&gt;It&#39;s handy to have firebug in the firefox that webdriver opens so use the profile manager to create a profile called test and then change your IntelliJ JUnit Run configuration VM Parameters to include &#39;-Dgeb.driver=firefox -Dwebdriver.firefox.profile=test&#39;&lt;br /&gt;&lt;br /&gt;Now you when you right click and run your test, IntelliJ will first compile everything and hopefully run your test. I say hopefully because I have a bunch of inline plugins so I have to exclude them from the compile path and hope for the best. Setting breakpoints and choosing debug lets you step through your test and let you can use firebug within the browser.&lt;br /&gt;&lt;br /&gt;There&#39;s a few things to be aware of. Groovy&#39;s property setters don&#39;t seem to work so you can&#39;t do stuff like user.username, instead you have to use the setter or if there isn&#39;t one you can use setProperty(). Spread operators don&#39;t work too well either, so you can&#39;t do User.list()*.delete().&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Update: forgot to mention that you should run the app in test mode or Remote Control will not set up its listener unlesss you set remoteControl.enabled to true in your app config&lt;/span&gt;</description><link>http://stateyourbizness.blogspot.com/2011/02/remote-controlled-gebspock-functional.html</link><author>noreply@blogger.com (Shin Tai)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-1181717603445030860</guid><pubDate>Tue, 07 Dec 2010 13:18:00 +0000</pubDate><atom:updated>2010-12-07T13:27:49.027+00:00</atom:updated><title>Testing cron expressions in Grails Jobs</title><description>One big problem I have is I can never remember what the cron expression is supposed to be and once I&#39;ve got it in the code if it is actually correct.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Very simple test below.  I create a CronTrigger and pass in the expression from the job.  I then check that it will fire by passing in a Calendar object.  The only key here is you can&#39;t test something in the past hence why I am adding another day to the LocalDate object.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;void testJobSchedule() {&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space:pre&quot;&gt; &lt;/span&gt;def trigger = new CronTrigger(&quot;name&quot;, &quot;group&quot;, JobName.cronExpression)&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space:pre&quot;&gt; &lt;/span&gt;assertTrue &quot;job should fire at 1:15&quot;, trigger.willFireOn(time(1, 15))&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space:pre&quot;&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;private Calendar time(int hour, int minute) {&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space:pre&quot;&gt; &lt;/span&gt;new LocalDate().plusDays(1).toDateTime(new LocalTime(hour, minute, 0, 0)).toCalendar(Locale.UK)&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully this helps someone out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description><link>http://stateyourbizness.blogspot.com/2010/12/testing-cron-expressions-in-grails-jobs.html</link><author>noreply@blogger.com (Glenn Saqui)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8243410482878657811</guid><pubDate>Fri, 19 Nov 2010 09:58:00 +0000</pubDate><atom:updated>2010-11-19T10:01:11.490+00:00</atom:updated><title>Unexpected search results</title><description>Bit of friday fun - just tried searching for Node GString, and Google helpfully suggested...&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;spell&quot; style=&quot;color: rgb(204, 0, 0);&quot;&gt;Did you mean: &lt;/span&gt;&lt;a href=&quot;http://www.google.co.uk/custom?hl=en&amp;amp;client=google-coop&amp;amp;cof=FORID:9%3BAH:left%3BCX:Foxstart%2520UK%2520-%2520M%2520-%2520SB%3BL:http://www.google.com/intl/en/images/logos/custom_search_logo_sm.gif%3BLH:30%3BLP:1%3BVLC:%23663399%3BDIV:%2397a5b0%3B&amp;amp;rurl=http://uk.foxstart.com/search.php%3Fq%3Dnode%2Bgstring%26cx%3D009900900170867307223:6nxc54q8niu%26cof%3DFORID:9%26ie%3DUTF-8%26rls%3Den:uk:ma%26src%3Dffsb%26google_rsg%3D__SPZwPJXI-xiTTCL7e7whl3WEaY0%3D&amp;amp;cx=009900900170867307223:6nxc54q8niu&amp;amp;rls=en:uk:ma&amp;amp;ad=w9&amp;amp;adkw=AELymgUizDhXn32qA9DNwYE1QXb2j1nmzrIO7r3MZnEw4j-i-syk1a9kqEuEcJxpP4teNs2mw1nMmQSVb6-Y0B9ZPFQY0rZ1sJIOp0zNWclUaljiAFZxcP8&amp;amp;&amp;amp;sa=X&amp;amp;ei=lkrmTIeYJcX2sgbv7sWgCw&amp;amp;ved=0CA0QBSgA&amp;amp;q=nude+g+string&amp;amp;spell=1&quot; class=&quot;spell&quot;&gt;&lt;b&gt;&lt;i&gt;nude&lt;/i&gt;&lt;/b&gt; &lt;b&gt;&lt;i&gt;g string&lt;/i&gt;&lt;/b&gt;&lt;/a&gt;</description><link>http://stateyourbizness.blogspot.com/2010/11/unexpected-search-results.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8852985638475562088</guid><pubDate>Fri, 19 Nov 2010 00:44:00 +0000</pubDate><atom:updated>2010-11-19T13:36:14.602+00:00</atom:updated><title>Using Liquibase DropAll Automagically 2</title><description>A while back &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_0&quot;&gt;gus&lt;/span&gt; &lt;a href=&quot;http://stateyourbizness.blogspot.com/2008/08/using-liquibase-dropall-automagically.html&quot;&gt;posted&lt;/a&gt; about how to get &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_1&quot;&gt;liquibase&lt;/span&gt; to drop all on application start up. He had to jump through some hoops because &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_2&quot;&gt;dependsOn&lt;/span&gt; wasn&#39;t working properly. This seems to be OK now so I think the process can be simplified a bit...&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Assuming the &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_3&quot;&gt;changelog&lt;/span&gt; is specified in grails-app/&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_4&quot;&gt;conf&lt;/span&gt;/&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_5&quot;&gt;liquibase&lt;/span&gt;/master.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_6&quot;&gt;xml&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;resources.groovy&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;if (config.liquibase.on) {&lt;br /&gt;   liquibaseDropAll(LiquibaseDropAll) { bean -&gt;&lt;br /&gt;      dataSource = dataSource&lt;br /&gt;      changeLog = &quot;classpath:liquibase/master.xml&quot;&lt;br /&gt;      bean.initMethod = &#39;init&#39;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   liquibase(SpringLiquibase) { bean -&gt;&lt;br /&gt;      &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_7&quot;&gt;dataSource&lt;/span&gt; = &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_8&quot;&gt;dataSource&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_9&quot;&gt;changeLog&lt;/span&gt; = &quot;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_10&quot;&gt;classpath&lt;/span&gt;:&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_11&quot;&gt;liquibase&lt;/span&gt;/master.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_12&quot;&gt;xml&lt;/span&gt;&quot;&lt;br /&gt;      bean.&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_13&quot;&gt;dependsOn&lt;/span&gt; = [&#39;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_14&quot;&gt;liquibaseDropAll&lt;/span&gt;&#39;]&lt;br /&gt;   }&lt;br /&gt;}&lt;/code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: monospace; font-size: 13px; &quot;&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_15&quot;&gt;LiquibaseDropAll&lt;/span&gt;.groovy&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;pre&gt;import liquibase.spring.SpringLiquibase&lt;br /&gt;import org.codehaus.groovy.grails.commons.ConfigurationHolder&lt;br /&gt;&lt;br /&gt;class &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_16&quot;&gt;LiquibaseDropAll&lt;/span&gt; extends &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_17&quot;&gt;SpringLiquibase&lt;/span&gt; {&lt;br /&gt;&lt;br /&gt;   void &lt;span class=&quot;blsp-spelling-error&quot; id=&quot;SPELLING_ERROR_18&quot;&gt;init&lt;/span&gt;() {&lt;br /&gt;      if (ConfigurationHolder.config.liquibase.dropAll) {&lt;br /&gt;         super.createLiquibase(dataSource.connection).dropAll()&lt;br /&gt;      }&lt;br /&gt;   }&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;Disclaimer: I&#39;ve only just started using it so it may still thow up some gotchas.&lt;/div&gt;&lt;/div&gt;</description><link>http://stateyourbizness.blogspot.com/2010/11/using-liquibase-dropall-automagically-2.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-2930095979125686010</guid><pubDate>Sun, 17 Oct 2010 11:00:00 +0000</pubDate><atom:updated>2010-10-17T12:17:09.269+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">caching</category><category domain="http://www.blogger.com/atom/ns#">F5</category><category domain="http://www.blogger.com/atom/ns#">Fast Cache</category><category domain="http://www.blogger.com/atom/ns#">Zeus</category><title>Reducing backend load</title><description>I&#39;ve recently been looking at alternatives to F5 and I remember from this year&#39;s QCon a lot of people mentioning Zeus so I thought I&#39;d give them a look.&lt;br /&gt;&lt;br /&gt;So far they look promising; being able to run Zeus on your own generic hardware could be a cost saving in the long run. For example we had to buy some spare PSUs out of fear we wouldn&#39;t be able to buy them in the future.&lt;br /&gt;&lt;br /&gt;One feature I really like the sound of is the &quot;webcache!refresh_time&quot;. It smooths out the load to your backend by only sending one request to your appserver while serving the rest from cache. For sites that must have low cache times this makes a lot of sense. If you get 30 requests per second for an item, you only send one request to your backend as it expires from cache.&lt;br /&gt;&lt;br /&gt;Turns out F5 also have a similar sounding feature called Fast Cache but for us it would be an additional module (read additional cost).&lt;br /&gt;&lt;br /&gt;If anyone has experience with either I&#39;d love to hear their thoughts.</description><link>http://stateyourbizness.blogspot.com/2010/10/reducing-backend-load.html</link><author>noreply@blogger.com (Shin Tai)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-5655194533665186701</guid><pubDate>Thu, 23 Sep 2010 07:11:00 +0000</pubDate><atom:updated>2010-09-23T09:02:15.345+01:00</atom:updated><title>Stubbing g.message</title><description>It&#39;s easy to mock grails taglibs using gmock and hamcrest. You can do something like...&lt;pre&gt;&lt;br /&gt;    ...&lt;br /&gt;    def g&lt;br /&gt;&lt;br /&gt;    void setup() {&lt;br /&gt;        g = mock()        &lt;br /&gt;        mock(tagLib).getG().returns(g).stub()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void someTest() {&lt;br /&gt;        g.message(hasEntry(&#39;code&#39;, &#39;foo.bar&#39;)).returns(&#39;FOO BAR&#39;)&lt;br /&gt;        String result&lt;br /&gt;        play {&lt;br /&gt;            result = tagLib.someMethod([:]).toString()&lt;br /&gt;        }&lt;br /&gt;        assert result.contains(&#39;FOO BAR&#39;)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But when you&#39;ve got a lot of calls to g.message this can become noisy and usually ends up being repeated in multiple tests. One option is to be relax the argument matching and switch to using a stub.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        g.message(instanceOf(Map)).returns(&#39;FOO BAR&#39;).stub()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is fine for the tests where you don&#39;t really care about the message, but too loose for the ones you do. I&#39;m playing with the an alternative which gives you both stubbing and the option of explicitly asserting g.message was called with the correct arguments. Be warned though it may raise a WTF exception on first glance.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    ...&lt;br /&gt;    def g&lt;br /&gt;&lt;br /&gt;    void setup() {&lt;br /&gt;        g = mock()        &lt;br /&gt;        mock(tagLib).getG().returns(g).stub()&lt;br /&gt;        stubMessages(g)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void someTest() {&lt;br /&gt;        String result&lt;br /&gt;        play {&lt;br /&gt;            result = tagLib.someMethod([:]).toString()&lt;br /&gt;        }&lt;br /&gt;        assert result.contains(&#39;code:foo.bar&#39;)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class MessageMatcher extends BaseMatcher {&lt;br /&gt;&lt;br /&gt;    String code = &#39;&#39;&lt;br /&gt;&lt;br /&gt;    static void stubMessages(def g) {&lt;br /&gt;        MessageMatcher matcher = new MessageMatcher()&lt;br /&gt;        g.message(matcher).returns(matcher).stub()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    boolean matches(Object o) {&lt;br /&gt;        code = ((Map) o).containsKey(&#39;code&#39;) ? o.code : &#39;&#39;&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void describeTo(Description description) { }&lt;br /&gt;&lt;br /&gt;    String toString() {&lt;br /&gt;        return &quot;code:${code}&quot;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The tricky bit was getting the g.message stub to return a value derived from the matcher arguments. I couldn&#39;t just do&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;g.message(matcher).returns(matcher.code).stub()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;because matcher.code won&#39;t have a value at this point. The solution is to override the matcher&#39;s toString() method to return the code and rely on groovy / grails invoking toString() when adding the matcher to the output. This certainly violates the rule of least surprises, but I think I&#39;m OK with that if it reduces duplication and the noise level of my tests - at least until I find a better way.</description><link>http://stateyourbizness.blogspot.com/2010/09/stubbing-gmessage.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-6284346353752752128</guid><pubDate>Fri, 17 Sep 2010 13:48:00 +0000</pubDate><atom:updated>2010-09-17T15:11:24.403+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gmock</category><category domain="http://www.blogger.com/atom/ns#">gpath</category><category domain="http://www.blogger.com/atom/ns#">markupbuilder</category><category domain="http://www.blogger.com/atom/ns#">spock</category><category domain="http://www.blogger.com/atom/ns#">taglibs</category><category domain="http://www.blogger.com/atom/ns#">tdd</category><category domain="http://www.blogger.com/atom/ns#">testing</category><title>Clean TagLib Tests</title><description>Despite my best efforts I&#39;ve always found it hard to write clean taglib tests. Now thanks to Spock and GroovyShell things are getting easier...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    void setup() {&lt;br /&gt;        mockDomain Invoice&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def &quot;Attachments icon has correct markup&quot;() {&lt;br /&gt;        given:&lt;br /&gt;        Invoice invoice = new InvoiceBuilder().buildAndSave()&lt;br /&gt;&lt;br /&gt;        when:&lt;br /&gt;        renderAttachmentsIcon([target: invoice])&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        valueOf(&#39;img.@id&#39;) == &quot;toggle-attachments-${invoice.id}&quot;&lt;br /&gt;        valueOf(&#39;script&#39;) == &quot;\$(&#39;#toggle-attachments-${invoice.id}&#39;).bind(&#39;click&#39;, Books.attachments.toggle);&quot;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Because I want to use GPath make assertions about the resulting HTML I&#39;ve overriden TagLibSpec&#39;s methodMissing closure as follows... &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def methodMissing(String name, args) {&lt;br /&gt;        String html = super.methodMissing(name, args)&lt;br /&gt;        createDocument(html)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    void createDocument(String html) {&lt;br /&gt;        String xml = &quot;&amp;lt;results&gt;${html}&amp;lt;/results&gt;&quot;&lt;br /&gt;        document = new XmlSlurper().parseText(xml)&lt;br /&gt;    }    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And added helper methods for evaluating GPath expressions...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    String valueOf(String gPath) {&lt;br /&gt;        evaluate(gPath).text()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    GPathResult evaluate(String gPath) {&lt;br /&gt;        new GroovyShell(new Binding(document: document)).evaluate(&quot;document.${gPath}&quot;)&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There&#39;s a little bit more to this story unfortunately...&lt;br /&gt;&lt;br /&gt;Firstly my taglibs use the MarkupBuilder and when run from my Spock test this only outputs the opening tag of the first element I genererate. I haven&#39;t had a chance to look into this yet, but a workaround is to add &quot;out &lt;&lt; &#39;&#39; to the end of the taglib method&lt;br /&gt;&lt;br /&gt;Secondly Spock interactions aren&#39;t yet as powerful as gmock, so I usually end up adding code to (g)mock grails taglibs.&lt;br /&gt;&lt;br /&gt;Thirdly another one of my tests outputs &amp;amp;nbsp; in the HTML which causes the XML parsing to barf. The solution is to map the &amp;amp;nbsp entity to a known character (in this case underscore).&lt;br /&gt;&lt;br /&gt;Finally there was a bug in Grails 1.3.3 / Spock 0.5 which breaks mockDomain. This is reportedly fixed in 1.3.4 and the latest Spock code, but I haven&#39;t tried upgrading yet.&lt;br /&gt;&lt;br /&gt;Here&#39;s how things really look...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@WithGMock&lt;br /&gt;class MetaAttachmentsTagLibSpec extends TagLibSpec {&lt;br /&gt;&lt;br /&gt;    def g&lt;br /&gt;    def document&lt;br /&gt;&lt;br /&gt;    void setup() {&lt;br /&gt;        g = mock()        &lt;br /&gt;        mock(tagLib).getG().returns(g).stub()&lt;br /&gt;        mockDomain Invoice&lt;br /&gt;&lt;br /&gt;        PluginManagerHolder.pluginManager = [hasGrailsPlugin: { String name -&gt; true }] as GrailsPluginManager // Workaround for JIRA GRAILS-6482       &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def cleanup() {&lt;br /&gt;        PluginManagerHolder.pluginManager = null // Workaround for JIRA GRAILS-6482&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def &quot;Attachments icon has correct markup&quot;() {&lt;br /&gt;        given:&lt;br /&gt;        Invoice invoice = new InvoiceBuilder().buildAndSave()&lt;br /&gt;        g.resource(instanceOf(Map)).returns &#39;/foo.jpg&#39;&lt;br /&gt;&lt;br /&gt;        when:&lt;br /&gt;        renderAttachmentsIcon([target: invoice])&lt;br /&gt;&lt;br /&gt;        then:&lt;br /&gt;        valueOf(&#39;img.@id&#39;) == &quot;toggle-attachments-${invoice.id}&quot;&lt;br /&gt;        valueOf(&#39;img.@src&#39;) == &quot;/foo.jpg&quot;&lt;br /&gt;        valueOf(&#39;script&#39;) == &quot;\$(&#39;#toggle-attachments-${invoice.id}&#39;).bind(&#39;click&#39;, Books.attachments.toggle);&quot;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    def methodMissing(String name, args) {&lt;br /&gt;        String html&lt;br /&gt;        play {&lt;br /&gt;            html = super.methodMissing(name, args)&lt;br /&gt;        }&lt;br /&gt;        createDocument(html)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def createDocument(String html) {&lt;br /&gt;        String xml = &quot;&quot;&quot;&amp;lt;!DOCTYPE html [&amp;lt;!ENTITY nbsp &quot;_&quot;&gt;]&gt;\n&amp;lt;results&gt;${html}&amp;lt;/results&gt;&quot;&quot;&quot;&lt;br /&gt;        document = new XmlSlurper().parseText(xml)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the method under test...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def renderAttachmentsIcon = { Map attrs, def body -&gt;&lt;br /&gt;        String targetId = attrs.target.id&lt;br /&gt;        String iconId = &quot;toggle-attachments-${targetId}&quot;&lt;br /&gt;        String imgSrc = g.resource(dir:&#39;/images/skin&#39;, file:&#39;paperclip.png&#39;)&lt;br /&gt;&lt;br /&gt;        MarkupBuilder builder = new MarkupBuilder(out)&lt;br /&gt;        builder.img(id: iconId, src: imgSrc)&lt;br /&gt;        builder.script(type:&#39;text/javascript&#39;) {&lt;br /&gt;            mkp.yield &quot;\$(&#39;#${iconId}&#39;).bind(&#39;click&#39;, Books.attachments.toggle);&quot;&lt;br /&gt;        }&lt;br /&gt;        out &amp;lt;&amp;lt; &#39;&#39; // flush for unit tests        &lt;br /&gt;    }    &lt;br /&gt;&lt;/pre&gt;</description><link>http://stateyourbizness.blogspot.com/2010/09/clean-taglib-tests.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-62184566768959674</guid><pubDate>Thu, 02 Sep 2010 13:08:00 +0000</pubDate><atom:updated>2010-09-02T14:20:06.649+01:00</atom:updated><title>Internet Explorer and the 1 item remaining bug</title><description>We&#39;ve started using Selenium 2 / WebDriver to soak test our application, and were caught once again by a bug in ie7 and ie8 that randomly causes the browser to hang, waiting for some resource to finish loading, even though the page is visible and works fine.&lt;br /&gt;&lt;br /&gt;I hit the problem a year or so ago and solved it by hacking something in prototype.js, but can&#39;t remember exactly what. Thankfully there&#39;s now a more recent version of prototype (we&#39;re stuck on grails 1.1.1 which is bundled with prototype 1.6.0), so I upgraded to prototype 1.6.1 and problem solved :)</description><link>http://stateyourbizness.blogspot.com/2010/09/internet-explorer-and-1-item-remaining.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-7758162600854591180</guid><pubDate>Sat, 07 Aug 2010 08:33:00 +0000</pubDate><atom:updated>2010-08-07T09:37:16.213+01:00</atom:updated><title>Grails and unit#junit;4.8.1: configuration not found in junit#junit;4.8.1:</title><description>After upgrading to grails 1.3.x I started getting the following error...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  ::::::::::::::::::::::::::::::::::::::::::::::&lt;br /&gt;&lt;br /&gt;  ::          UNRESOLVED DEPENDENCIES         ::&lt;br /&gt;&lt;br /&gt;  ::::::::::::::::::::::::::::::::::::::::::::::&lt;br /&gt;&lt;br /&gt;  :: junit#junit;4.8.1: configuration not found in junit#junit;4.8.1: &#39;master&#39;. It was required from org.grails.internal#Books;0.1 test&lt;br /&gt;&lt;br /&gt;  ::::::::::::::::::::::::::::::::::::::::::::::&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A found a few posts suggesting I needed to clear my ivy cache, but that did sfa. Turned out to be something in the jawr 3.3.2 plugin. It went away when I excluded junit from compile scope in the plugins dependencies.groovy&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    dependencies {&lt;br /&gt;        // specify dependencies here under either &#39;build&#39;, &#39;compile&#39;, &#39;runtime&#39;, &#39;test&#39; or &#39;provided&#39; scopes eg.&lt;br /&gt;     compile (&#39;net.jawr:jawr:3.3.2&#39;) {&lt;br /&gt;      excludes &quot;mail&quot;, &quot;activation&quot;, &quot;ejb&quot;,&quot;jms&quot;,&quot;jmxri&quot;,&quot;jmxremote&quot;, &quot;junit&quot;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;</description><link>http://stateyourbizness.blogspot.com/2010/08/grails-and-unitjunit481-configuration.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-3712076851389095829</guid><pubDate>Fri, 23 Jul 2010 14:52:00 +0000</pubDate><atom:updated>2010-07-23T15:53:54.035+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">grails</category><category domain="http://www.blogger.com/atom/ns#">intellij</category><category domain="http://www.blogger.com/atom/ns#">subversion intellij</category><title>IntelliJ v9.0.3 adds support for Grails v1.3.x</title><description>JetBrains released IntelliJ IDEA v9.0.3 two days ago, which includes support for Grails v1.3.x, along with nicer SVN merging.&lt;br /&gt;&lt;br /&gt;See more details here:&lt;br /&gt;&lt;br /&gt;http://www.jetbrains.com/idea/whatsnew/index.html</description><link>http://stateyourbizness.blogspot.com/2010/07/intellij-v903-adds-support-for-grails.html</link><author>noreply@blogger.com (Dan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-1202564260244889419</guid><pubDate>Sun, 02 May 2010 09:41:00 +0000</pubDate><atom:updated>2010-05-02T11:08:31.002+01:00</atom:updated><title>AppStatus Plugin 0.1 Released</title><description>The &lt;a href=&quot;http://plugins.energizedwork.com/grails-app-status/tags/LATEST_RELEASE/&quot;&gt;AppStatus plugin&lt;/a&gt; enables you to easily display useful info about your application.&lt;br /&gt;&lt;br /&gt;Install the plugin and navigate to http://yourapp/appStatus to see application.properties, server time and locale.&lt;br /&gt;&lt;br /&gt;If you want to see more details you can specify the &quot;providers&quot; in resources.groovy&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;import uk.co.acuminous.app.status.provider.*&lt;br /&gt;import uk.co.acuminous.app.status.AppStatusConfig&lt;br /&gt;&lt;br /&gt;beans = {&lt;br /&gt;    appStatusConfig(AppStatusConfig) {&lt;br /&gt;        providers = [&lt;br /&gt;&lt;br /&gt;            // !!!DANGER WILL ROBINSON!!!&lt;br /&gt;            // The ApplicationConfigProvider will dump the entire&lt;br /&gt;            // contents of Config.groovy including datasource.password&lt;br /&gt;            // The SystemPropertiesProvider could also make available&lt;br /&gt;            // potentially sensitive system variables&lt;br /&gt;&lt;br /&gt;            properties: new ApplicationPropertiesProvider(),&lt;br /&gt;            config: new ApplicationConfigProvider(),&lt;br /&gt;            system: new SystemPropertiesProvider(),&lt;br /&gt;            locale: new LocaleProvider()&lt;br /&gt;        ]&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you want to add your own providers just write something that implements the Provider interface and add it to the providers map.&lt;br /&gt;&lt;br /&gt;Finally if you&#39;re already using &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt; and &lt;a href=&quot;http://jqueryui.com/&quot;&gt;jQuery UI&lt;/a&gt; you pick an nicer view&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;beans = {&lt;br /&gt;    appStatusConfig(AppStatusConfig) {&lt;br /&gt;        providers = [&lt;br /&gt;            // blah&lt;br /&gt;        ]&lt;br /&gt;        view = &#39;tabs&#39;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;</description><link>http://stateyourbizness.blogspot.com/2010/05/appstatus-plugin-01-released.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-82259971118310798</guid><pubDate>Sat, 24 Apr 2010 05:40:00 +0000</pubDate><atom:updated>2010-04-28T09:36:34.081+01:00</atom:updated><title>Pure Genius and mod_jk</title><description>I&#39;m currently developing an application for &lt;a href=&quot;http://en.wikipedia.org/wiki/Alex_(comic_strip)&quot;&gt;MegaBank&lt;/a&gt; which makes heavy use of AJAX. The latest cut was throwing javascript errors in UAT but not in development. A bit of investigation with firebug showed that when an AJAX request returned 404 (which it does if the user supplies a non-existent cost code for example), the next AJAX request would respond with the &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_sign-on&quot;&gt;SSO&lt;/a&gt; login page instead of the expected json response. Further investigation showed that the second AJAX response had been served by a different node than the one it was sent to, resulting in the SSO challenge.&lt;br /&gt;&lt;br /&gt;Request had a cookie:&lt;br /&gt;jsessionid=ASAD123DFDFS83242SDFASD9234234.node1&lt;br /&gt;&lt;br /&gt;Response has a set-cookie header:&lt;br /&gt;jsessionid=SDFSDF234DFSLFSD324234880SDFSDL.node2&lt;br /&gt;&lt;br /&gt;i.e. our sticky session was becoming unstuck.&lt;br /&gt;&lt;br /&gt;We reported the incident to our support team, who&#39;s spanked it straight back over the net with the wonderfully helpful &quot;It&#39;s an application config issue&quot;. Great. Thanks. Our app doesn&#39;t do anything clever with cookies. There is no logout button. We never invalidate the session. We&#39;d already checked that inbound request had the right jsession id, and also that the associated response had a set-cookie header from the wrong node. Furthermore the app server logs show that the second request didn&#39;t even hit the right node. Back to web support with an offer to demonstrate the problem and walk through why we believe it&#39;s an issue with the load balancer. Even if it turned out to be an issue with the app we would need their help to diagnose it.&lt;br /&gt;&lt;br /&gt;Offer accepted. And &quot;Pure Genius&quot; arrives (That&#39;s not his real name, but it is what was written on his cuff links). The first words out of his mouth were, &quot;We support 100s of applications and the load balancer works fine. It must be your application&quot;. It doesn&#39;t mater that this is a bank, where 99% of the applications he supports are legacy and have probably never heard of AJAX. So I walk him through the process, show him the HTTP headers, show him the logs, explain that this only seems to happen after a 404. He goes away and helpfully reports...&lt;br /&gt;&lt;br /&gt;&quot;It&#39;s an application configuration issue.&quot;&lt;br /&gt;&lt;br /&gt;Grrrrrrrr. Escalate. Now engineering areinvolved. Helpfully &quot;Pure Genius&quot; has already told them it&#39;s a problem with our app, so they&#39;ve they&#39;ve prioritised it to the bottom of their queue. Grrrrrrrr. Another round of the escalation game follows and we get someone from engineering who knows what they&#39;re doing and isn&#39;t wearing blinkers. Guess what? There&#39;s a bug in mod_jk which causes it to fail a session over if it gets a non 200 error code with no content, so we added the words &quot;Pure Genius&quot; to the response and we have sticky sessions again. I guess he helped after all.</description><link>http://stateyourbizness.blogspot.com/2010/04/pure-genius-and-modjk.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-6469721797516647897</guid><pubDate>Thu, 18 Feb 2010 11:02:00 +0000</pubDate><atom:updated>2010-02-18T11:13:21.662+00:00</atom:updated><title>Javassist Enhancement failed</title><description>Just spent the last few hours debugging this.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;def adoptChild = {&lt;br /&gt;   Parent p = Parent.get(params.id)&lt;br /&gt;   p.child = Child.findByName(params.name)&lt;br /&gt;   assert p.save(flush:true)&lt;br /&gt;   redirect(action: &#39;showParentWithChild&#39;, id: p.id)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def showParentWithChild() {&lt;br /&gt;   Parent p = Parent.get(params.id) // Javassist Enhancement failed stack trace here&lt;br /&gt;   render(&quot;OK&quot;)&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Turned out that the child class had a private constructor (no idea why). I ditched the constructor and everything was back to normal.</description><link>http://stateyourbizness.blogspot.com/2010/02/javassist-enhancement-failed.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-6515148688831849981</guid><pubDate>Tue, 26 Jan 2010 15:56:00 +0000</pubDate><atom:updated>2010-01-26T16:13:27.157+00:00</atom:updated><title>Issues with Eclipse 3.5.1 and groovy plug-in</title><description>&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;For all you Linuxy peeps.&lt;br /&gt;&lt;br /&gt;After installing Eclipse 3.5.1 (SDK version) I installed all the plugins I usually use but when I installed the groovy v2 plugin all my existing plugins disappeared along with the groovy one.  Eclipse insisted that they were installed but they weren&#39;t there.&lt;br /&gt;&lt;br /&gt;It seems that this combination doesn&#39;t like &quot;shared installs&quot;.  My eclipse installation was in /usr/local/eclipse and I was installing the groovy plugin as my regular user.  Fail.&lt;br /&gt;&lt;br /&gt;There are two solutions.&lt;br /&gt;&lt;br /&gt;1 - install a local copy of eclipse.&lt;br /&gt;&lt;br /&gt;Simple but it means an eclipse install per user on your machine.&lt;br /&gt;&lt;br /&gt;2 - install the groovy plugin as root.&lt;br /&gt;&lt;br /&gt;Means that you have to run it as root every time you want to upgrade the plugin.&lt;br /&gt;&lt;br /&gt;Choose whichever evil is lesser for you.  (I chose #2).&lt;br /&gt;&lt;br /&gt;BTW you may also need this magic shell script line&lt;br /&gt;&lt;br /&gt;export GDK_NATIVE_WINDOWS=true&lt;br /&gt;&lt;br /&gt;if you find that some of the buttons in eclipse don&#39;t like being clicked on.  Apparently this is due to be fixed in eclipse 3.5.2.&lt;br /&gt;&lt;br /&gt;Hope this saves someone a few frustrated hours.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;</description><link>http://stateyourbizness.blogspot.com/2010/01/issues-with-eclipse-351-and-groovy-plug.html</link><author>noreply@blogger.com (Darren)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-5040929482451236597</guid><pubDate>Fri, 08 Jan 2010 17:12:00 +0000</pubDate><atom:updated>2010-01-08T17:32:14.408+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">gmock</category><category domain="http://www.blogger.com/atom/ns#">hamcrest</category><category domain="http://www.blogger.com/atom/ns#">map</category><category domain="http://www.blogger.com/atom/ns#">taglibs</category><title>Ham and Chips</title><description>&lt;a href=&quot;http://adhockery.blogspot.com/2010/01/using-gmock-to-complement-grails.html&quot;&gt;Rob Fletcher&#39;s blog post on gMock&lt;/a&gt; inspired me to try out hamcrest, but I was surprised to find out there&#39;s no simple way to match collections in mocked method arguments - the best I could come up with was this...&lt;br /&gt;&lt;pre&gt;mock(tagLib).fieldLabel(instanceOf(Map), instanceOf(Closure)).returns(&quot;&amp;lt;label&amp;gt;&amp;lt;/label&amp;gt;&quot;)&lt;/pre&gt;which doesn&#39;t tell me whether I&#39;m calling fieldLabel with the expected attributes. After a bit of searching I found the MapContentMatcher in the Spring Integration library, but didn&#39;t want include the whole jar just for that. It also had dependencies other libraries and was heavily typed with generics. Here&#39;s the cut down groovy version...&lt;br /&gt;&lt;pre&gt;import org.hamcrest.*&lt;br /&gt;import static org.hamcrest.core.AllOf.*&lt;br /&gt;import org.hamcrest.Factory as HamcrestFactory&lt;br /&gt;&lt;br /&gt;class MapContentMatcher extends TypeSafeDiagnosingMatcher&amp;lt;Map&amp;gt; {&lt;br /&gt;&lt;br /&gt;    Object key&lt;br /&gt;    Object value&lt;br /&gt;    &lt;br /&gt;    MapContentMatcher(Object key, Object value) {&lt;br /&gt;     this.key = key&lt;br /&gt;        this.value = value&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public boolean matchesSafely(Map actual, Description mismatchDescription) {&lt;br /&gt;     return actual.containsKey(key) &amp;&amp; value == actual[key]&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void describeTo(Description description) {&lt;br /&gt;     description.appendText(&quot;$key:$value&quot;)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @HamcrestFactory&lt;br /&gt;    public static Matcher hasAllEntries(Map expected) {&lt;br /&gt;     return allOf(expected.collect { k, v -&gt;&lt;br /&gt;      new MapContentMatcher(k, v)&lt;br /&gt;        })&lt;br /&gt;    }    &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Which can be used thus...&lt;br /&gt;&lt;pre&gt;mock(tagLib).fieldLabel(hasAllEntries([id: expectedField, label:expectedHeading]), instanceOf(Closure)).returns(&quot;&amp;lt;label&amp;gt;&amp;lt;/label&amp;gt;&quot;)&lt;/pre&gt;</description><link>http://stateyourbizness.blogspot.com/2010/01/ham-and-chips.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-479543106991657938</guid><pubDate>Thu, 07 Jan 2010 07:28:00 +0000</pubDate><atom:updated>2010-01-07T16:01:06.900+00:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">ajax</category><category domain="http://www.blogger.com/atom/ns#">grails</category><category domain="http://www.blogger.com/atom/ns#">layout</category><category domain="http://www.blogger.com/atom/ns#">sitemesh</category><title>Sitemesh layout applied to AJAX response (gotcha)</title><description>Grails supports multiple ways to specify a sitemesh layout for your responses. One way I wasn&#39;t familiar with is by convention, i.e. if you have a controller &#39;BookController&#39; and a layout in /views/layouts called book.gsp all the actions in BookController will be rendered with the book layout by default - even if you do render(&quot;some text&quot;) or render(template: &quot;/sometemplate&quot;).&lt;br /&gt;&lt;br /&gt;So if you&#39;re wondering why all your AJAX responses are getting wrapped up in a sitemesh template this could be the reason. You can stop this by changing the content type to text/plain or by renaming the layout and specifying it explicitly in your gsps using &amp;lt;meta name=&quot;layout&quot; content=&quot;layoutname&quot;/&amp;gt;.</description><link>http://stateyourbizness.blogspot.com/2010/01/sitemesh-layout-applied-to-ajax.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-3105094982700155667</guid><pubDate>Wed, 07 Oct 2009 07:41:00 +0000</pubDate><atom:updated>2009-10-07T08:43:44.225+01:00</atom:updated><title>Testing grails scripts</title><description>Not sure if everyone caught the new functionality that Peter has put into 1.2M3.  It&#39;s the ability to test grails scripts.  Heres the link to his blog post:&lt;br /&gt;&lt;a href=&quot;http://www.cacoethes.co.uk/blog/groovyandgrails/testing-your-grails-scripts&quot;&gt;http://www.cacoethes.co.uk/blog/groovyandgrails/testing-your-grails-scripts&lt;/a&gt;</description><link>http://stateyourbizness.blogspot.com/2009/10/testing-grails-scripts.html</link><author>noreply@blogger.com (Glenn Saqui)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-2832449118545226677</guid><pubDate>Thu, 17 Sep 2009 07:37:00 +0000</pubDate><atom:updated>2009-09-17T09:24:01.484+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">build</category><category domain="http://www.blogger.com/atom/ns#">disk</category><category domain="http://www.blogger.com/atom/ns#">linux</category><category domain="http://www.blogger.com/atom/ns#">openvz</category><category domain="http://www.blogger.com/atom/ns#">virtualization</category><title>Build Server Woes (mptscsi task abort)</title><description>I&#39;m posting this here for two reasons:&lt;br /&gt; &lt;ul&gt;&lt;li&gt;in the hope that someone out there will find this useful&lt;/li&gt;&lt;br /&gt; &lt;li&gt;personal therapy&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Scenario&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;We&#39;ve got a couple of build servers (x86_64 linux, openVZ) that have been having some disk I/O problems. These boxes (boxen) run various virtual machines related to our product builds - hudson masters &amp;amp; slaves, distribution servers, puppet master, test mail server, munin server... yada yada. You get the idea. They&#39;re kinda important.&lt;br /&gt;&lt;br /&gt;The problem manifests itself by first reporting errors like the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sep 16 14:28:51 hn3 mptscsih: ioc0: attempting task abort! (sc=ffff880422a348c0)&lt;br /&gt;Sep 16 14:28:51 hn3 sd 0:1:2:0: [sda] CDB: cdb[0]=0x2a: 2a 00 12 b2 fc 9f 00 00 08 00&lt;br /&gt;Sep 16 14:28:51 hn3 mptscsih: ioc0: Issue of TaskMgmt failed!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;followed shortly by the volume in question getting offlined into readonly mode:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Sep 16 14:29:41 hn3 mptscsih: ioc0: host reset: SUCCESS (sc=ffff880422a348c0)&lt;br /&gt;Sep 16 14:29:41 hn3 sd 0:1:2:0: Device offlined - not ready after error recovery&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This ain&#39;t that helpful when you&#39;ve got a whole load of hungry VMs wanting to write stuff to disk. A closer look at the disk controller yields the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;lspci&lt;br /&gt;...&lt;br /&gt;0b:00.0 SCSI storage controller: LSI Logic / Symbios Logic SAS1068E PCI-Express Fusion-MPT SAS (rev 08)&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A quick search through our messages shows the following related information:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;dmesg | grep -i mpt&lt;br /&gt;Fusion MPT base driver 3.04.07&lt;br /&gt;Fusion MPT SPI Host driver 3.04.07&lt;br /&gt;Fusion MPT FC Host driver 3.04.07&lt;br /&gt;Fusion MPT SAS Host driver 3.04.07&lt;br /&gt;mptsas 0000:0b:00.0: PCI INT A -&gt; GSI 35 (level, low) -&gt; IRQ 35&lt;br /&gt;mptbase: ioc0: Initiating bringup&lt;br /&gt;mptbase: ioc0: PCI-MSI enabled&lt;br /&gt;mptsas 0000:0b:00.0: setting latency timer to 64&lt;br /&gt;Fusion MPT misc device (ioctl) driver 3.04.07&lt;br /&gt;mptctl: Registered with Fusion MPT base driver&lt;br /&gt;mptctl: /dev/mptctl @ (major,minor=10,220)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A quick google turns up quite a few different issues with these controllers but no clear resolution (no surprise).&lt;br /&gt;&lt;br /&gt;To cut a (very) long story short we appear to have a solution by using the &lt;a href=&quot;http://www.lsi.com/storage_home/products_home/standard_product_ics/sas_ics/lsisas1068e/index.html?remote=1&amp;amp;locale=EN&quot;&gt;drivers supplied by LSI&lt;/a&gt; rather than those shipped with the latest linux kernel. Patching the kernel (by replacing the drivers/message/fusion folder with the equivalent found in LSI&#39;s MPTLINUX_RHEL5_SLES10_PH16-4.18.00.00-1.zip distribution) with version 4.18 of the MPT drivers has yielded an (apparently) stable system, tested under reasonably high load (load average ~20).&lt;br /&gt;&lt;br /&gt;Incidentally, for those of you who like acronyms, MPT stands for &#39;Message passing technology&#39;.&lt;br /&gt;&lt;br /&gt;My work here is done.</description><link>http://stateyourbizness.blogspot.com/2009/09/build-server-woes-mptscsi-task-abort.html</link><author>noreply@blogger.com (Gus Power)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-4363108990234935695</guid><pubDate>Mon, 17 Aug 2009 15:06:00 +0000</pubDate><atom:updated>2009-08-17T16:12:44.907+01:00</atom:updated><title>Dynamic UrlMapping using request parameters</title><description>Might be old news to some, but I just found you can assign closures to the action and controller values in URL mappings, e.g.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&quot;/update/$controller/$target&quot; {&lt;br /&gt;   action = {&lt;br /&gt;      &quot;update&quot; + params.target[0].toUpperCase() + params.target.substring(1);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Great for mapping restful style urls to meaningful action names, e.g.&lt;br /&gt;&lt;br /&gt;&quot;/update/patient/speciality&quot; =&gt; PatientController.updateSpeciality</description><link>http://stateyourbizness.blogspot.com/2009/08/dynamic-urlmapping-using-request.html</link><author>noreply@blogger.com (Stephen Cresswell)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-1301006382008151188</guid><pubDate>Sun, 05 Jul 2009 14:23:00 +0000</pubDate><atom:updated>2009-07-05T15:27:21.405+01:00</atom:updated><title>Selenium IDE 1.0.1</title><description>I recently upgraded to Selenium 1.0.1 and found that everything worked fine except that some asserts were failing around stored variables. e.g.&lt;br /&gt;&lt;br /&gt;storeText //h2   varname&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It turned out that if the text is hidden on the page then all that is stored is &#39;&#39;. In our case it was fixture pages that was returning some data as hidden page elements for reference.</description><link>http://stateyourbizness.blogspot.com/2009/07/selenium-ide-101.html</link><author>noreply@blogger.com (Agile Enforcer)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8670764473596772976</guid><pubDate>Wed, 24 Jun 2009 15:35:00 +0000</pubDate><atom:updated>2009-06-24T16:41:05.966+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">selenium</category><category domain="http://www.blogger.com/atom/ns#">selenium-ide</category><title>Selenium IDE</title><description>&lt;span style=&quot;font-family: verdana;&quot;&gt;Just a quick post to say that if any of you out there spend your day resizing and moving Selenium IDE after reopening it (it doesn&#39;t remember the previous window state), you can write a little script to do it for you using the handy &#39;wmctrl&#39; :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(on linux)&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;wmctrl -r &#39;Mozilla Firefox&#39; -e 0,0,25,1330,1125&lt;br /&gt;wmctrl -r &quot;Mozilla Firefox&quot; -b remove,maximized_vert,maximized_horz&lt;br /&gt;wmctrl -a &#39;Mozilla Firefox&#39;&lt;br /&gt;wmctrl -r &#39;Selenium IDE&#39; -e 0,1350,25,575,1125&lt;br /&gt;wmctrl -a &#39;Selenium IDE&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;The snippet above moves, unmaximises and raises firefox before moving and activiating the Selenium IDE. &lt;/span&gt;</description><link>http://stateyourbizness.blogspot.com/2009/06/selenium-ide.html</link><author>noreply@blogger.com (Gus Power)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-8931906748831835160</guid><pubDate>Tue, 23 Jun 2009 19:11:00 +0000</pubDate><atom:updated>2009-06-23T20:24:19.259+01:00</atom:updated><title>Custom constraint</title><description>The other day we were doing some refactoring and we started to look into how all our validation is done.  We noticed that we have a lot of duplication in our validators and wanted to do something about it.  We came across the following blog post that describes how to create a &lt;a href=&quot;http://jshingler.blogspot.com/2008/07/phone-number-custom-constraint-for.html&quot;&gt;custom validator&lt;/a&gt;. This is a great little blog post and allowed us to kill a lot code. &lt;br /&gt;&lt;br /&gt;One thing that we did notice was that they suggest that you put the registering of the custom validator in the Config.groovy file.  We found this problematic and found that the better solution was to put it in the resources.groovy file.  Another problem that we came across was that you needed to register the constraint in the unit test if you wanted to be able to test constraints.  This makes sense because resources.groovy isn&#39;t called in unit tests.&lt;br /&gt;&lt;br /&gt;To register your constraint use the following line of groovy code:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;ConstrainedProperty.registerNewConstraint(PhoneNumberConstraint.NAME, PhoneNumberConstraint)&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Hopefully this helps with some refactoring.&lt;br /&gt;Glenn</description><link>http://stateyourbizness.blogspot.com/2009/06/custom-constraint.html</link><author>noreply@blogger.com (Glenn Saqui)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4919603745642637061.post-6826596103178063708</guid><pubDate>Wed, 29 Apr 2009 08:43:00 +0000</pubDate><atom:updated>2009-04-29T10:01:51.313+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">CSS</category><category domain="http://www.blogger.com/atom/ns#">IE</category><category domain="http://www.blogger.com/atom/ns#">selenium</category><title>Selenium CSS locators</title><description>We&#39;ve got a project with quite a large set of tests, and we have both Firefox and IE7 continuous builds using selenium.  The annoying thing is that something that takes 5 minutes in Firefox can take 30+ minutes with IE (I kid you not!).&lt;br /&gt;&lt;br /&gt;It turns out this is a common problem and is due to the lack for native xpath support in IE.  So for all the selenium tests that use xpath=//..... in IE the xpath is actually being evaluated using javascript ... ouch.  An alternative is to use css locators, you can&#39;t do this everywhere but as well as improving the IE performance it can also provide some rather tidy rules. For example&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;xpath=//div[contains(@class,&#39;balance&#39;)]&lt;br /&gt;or&lt;br /&gt;css=.balance&lt;br /&gt;&lt;br /&gt;xpath=//div[@id,&#39;topLeft&#39;)//span[contains(@class,&#39;name&#39;)]  &lt;br /&gt;or &lt;br /&gt;css=#topLeft .name&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So even if you dont&#39; care about IE using css selectors might be a lot nicer.  (It might also improve your css skills!)</description><link>http://stateyourbizness.blogspot.com/2009/04/selenium-css-locators.html</link><author>noreply@blogger.com (Agile Enforcer)</author><thr:total>7</thr:total></item></channel></rss>