tag:blogger.com,1999:blog-59435708617116458042024-02-19T05:34:43.161+01:00refaktorEveryday struggle with Java, Spring, TDD and web developmentTomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-5943570861711645804.post-88776962567577929302015-10-20T13:52:00.000+02:002015-10-20T14:24:29.841+02:00How to recover after Hibernate's OptimisticLockException<p>I've read many articles about optimistic locking and OptimisticLockException itself. Problem is that each one of them ended up getting their first exception and no word on recovery. What to do next? Repeat? If so, how? Or drop it? Is there any chance to continue? How? Even more, documentation says that if you get Hibernate exception - you're done, it's not recoverable:</p>
<blockquote>An exception thrown by Hibernate means you have to rollback your database transaction and close the Session immediately (this is discussed in more detail later in the chapter). If your Session is bound to the application, you have to stop the application. Rolling back the database transaction does not put your business objects back into the state they were at the start of the transaction. This means that the database state and the business objects will be out of sync. Usually this is not a problem, because exceptions are not recoverable and you will have to start over after rollback anyway.
<footer>- <cite><a href="https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch13.html#transactions-optimistic" target="_blank">Hibernate 4.3 documentation, 13.1.4</a></cite></footer>
</blockquote>
<p>Here is my attempt on this: <strong>repeatable</strong> and <strong>recoverable</strong>.</p>
<h3>Business case</h3>
<p>Let's say we have distributed application with two web servers, connected to the same database. Applications use optimistic locking to avoid collisions. Customers buy lottery coupons, which are numbered from 1 to 100. In the same second Alice on web server 1 draws two coupons: 11 and 12. In the same moment Bob reserves two coupons on web server 2. It draws 11 and 13 for Bob and tries to write it back to database. But it fails, since Alice's commit was first. I want a web application server to draw coupons for Bob again and then - try to save again until it succeeds.</p>
<h3>Solution</h3>
<p>For every request Hibernate associates different Session that is flushed at the end of request processing. If you hit OptimisticLockException then this Request Session is polluted and will be rolled back. To avoid this we will create a separate Hibernate's Session especially for drawing coupons. If separate session fails - drop this session and try again in a new one. If it succeeds - merge it with a main request session. Request Session cannot be touched during draws. Take a look at the following picture:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJBCJ27xpVnvNLuQYPBQgxiRav_yLwePSWm7vLEkZXgcGD0Ipv08mwd6He2ZOCLyvDpEQ3B_7bw2hSWGSabY19Kun_c89K1YHTVmGsUFJqCSR8wFH2M4qygZUBnXwMu08c9PcUGcPseSs/s1600/optimistic+locking+2.png" imageanchor="1" style="clear: both"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJBCJ27xpVnvNLuQYPBQgxiRav_yLwePSWm7vLEkZXgcGD0Ipv08mwd6He2ZOCLyvDpEQ3B_7bw2hSWGSabY19Kun_c89K1YHTVmGsUFJqCSR8wFH2M4qygZUBnXwMu08c9PcUGcPseSs/s1600/optimistic+locking+2.png" /></a></div>
<p>On this picture yellow and green short-term sessions has failed with OptimisticLockException. Red session was successful and these objects are merged to a main session on the left.</p>
<h4>Reservation entity</h4>
<p>Key requirement here is to keep a domain you want to lock on as small as possible and not coupled directly to anything else. Best approach here is to create some <code><span class="class">Reservation</span></code> entity with few fields, let's say: <code><span class="field">couponId</span></code> and <code><span class="field">customerId</span></code>. For each <code><span class="class">Coupon</span></code> create one <code><span class="class">Reservation</span></code> row and use <code><span class="field">reserved</span></code> boolean field as a reservation status. For coupon and customer use weak identifiers (<code><span class="keyword">long</span></code>) instead of real entities. This way no object tree will be loaded and <code><span class="class">Reservation</span></code> stays decoupled.</p>
<pre><code><span class="keyword">import</span><span class="keyword"> </span><span class="annotation">lombok.Getter</span>;<br/><span class="keyword">import </span><span class="annotation">lombok.Setter</span>;<br/><span class="keyword">import </span><span class="annotation">lombok.ToString</span>;<br/><br/><span class="keyword">import </span><span class="annotation">javax.persistence.Column</span>;<br/><span class="keyword">import </span><span class="annotation">javax.persistence.Entity</span>;<br/><span class="keyword">import </span><span class="annotation">javax.persistence.Id</span>;<br/><br/><span class="keyword">import static </span><span class="class">org.apache.commons.lang3.Validate</span>.isTrue;<br/><span class="keyword">import static </span><span class="class">org.springframework.util.Assert</span>.isNull;<br/><br/><span class="annotation">@Getter<br/></span><span class="annotation">@Setter<br/></span><span class="annotation">@ToString<br/></span><span class="annotation">@Entity<br/></span><span class="keyword">public class </span><span class="class">Reservation </span>{<br/> <span class="annotation">@Id<br/></span><span class="annotation"> </span><span class="keyword">private long </span><span class="field">id</span>;<br/> <span class="annotation">@Column</span>(<span class="string">"coupon_id"</span>)<br/> <span class="keyword">private long </span><span class="field">couponId</span>;<br/> <span class="annotation">@Column</span>(<span class="string">"customer_id"</span>)<br/> <span class="keyword">private </span><span class="class">Long </span><span class="field">customerId</span>;<br/> <span class="annotation">@Column</span>(<span class="string">"is_reserved"</span>)<br/> <span class="keyword">private boolean </span><span class="field">reserved</span>;<br/><br/> <span class="keyword">public void </span><span class="method">reserve</span>(<span class="keyword">long </span><span class="parameter">reservingCustomerId</span>) {<br/> <span class="static">isTrue</span>(<span class="field">reserved </span>== <span class="keyword">false</span>);<br/> <span class="static">isNull</span>(<span class="field">customerId</span>);<br/> <span class="field">reserved </span>= <span class="keyword">true</span>;<br/> <span class="field">customerId </span>= <span class="parameter">reservingCustomerId</span>;<br/> }<br/>}</code></pre>
<p>Method <code><span class="method">reserve</span></code> has some business assertions to keep it legit. You can also spot <a href="https://projectlombok.org/" target="_blank">lombok</a>'s annotations that provide getters, setters and <code><span class="method">toString</span></code> methods on the fly.</p>
<h4>Reservation Service</h4>
<p>Reservation Service implements my solution. I've commented some steps for better reading. Please read a source code:</p>
<pre><code><span class="keyword">import </span><span class="annotation">lombok.extern.slf4j.Slf4j</span>;<br/><span class="keyword">import </span><span class="class">org.hibernate</span>.*;<br/><span class="keyword">import </span><span class="interface">org.hibernate.ejb.HibernateEntityManager</span>;<br/><span class="keyword">import </span><span class="class">org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException</span>;<br/><br/><span class="keyword">import </span><span class="class">javax.persistence.OptimisticLockException</span>;<br/><span class="keyword">import </span><span class="annotation">javax.persistence.PersistenceContext</span>;<br/><span class="keyword">import </span><span class="interface">java.util.List</span>;<br/><br/><span class="annotation">@Slf4j<br/></span><span class="keyword">public class </span><span class="class">ReservationService </span>{<br/><br/> <span class="annotation">@PersistenceContext<br/></span><span class="annotation"> </span><span class="keyword">private </span><span class="interface">HibernateEntityManager </span><span class="field">hibernateEntityManager</span>;<br/><br/> <span class="annotation">@SuppressWarnings</span>(<span class="string">"uncheked"</span>)<br/> <span class="keyword">private </span><span class="interface">Iterable</span><<span class="class">Reservation</span>> <span class="method">reserveOptimistic</span>(<span class="keyword">long </span><span class="parameter">customerId</span>, <span class="keyword">final int </span><span class="parameter">count</span>) <span class="keyword">throws </span><span class="class">NoFreeReservationsException </span>{<br/> <span class="static">log</span>.<span class="method">info</span>(<span class="string">"Trying to reserve {} reservations for customer {}"</span>, <span class="parameter">count</span>, <span class="parameter">customerId</span>);<br/><br/> <span class="comment">//This is the request session that needs to stay clean</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span><span class="interface">Session </span>currentSession = <span class="field">hibernateEntityManager</span>.<span class="method">getSession</span>();<br/> <span class="interface">Iterable</span><<span class="class">Reservation</span>> reserved = <span class="keyword">null</span>;<br/><br/> <span class="keyword">do </span>{<br/> <span class="comment">//This is our temporary session to work on</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span><span class="interface">Session </span>newSession = <span class="field">hibernateEntityManager</span>.<span class="method">getSession</span>().<span class="method">getSessionFactory</span>().<span class="method">openSession</span>();<br/> newSession.<span class="method">setFlushMode</span>(<span class="class">FlushMode</span>.<span class="static">COMMIT</span>);<br/> <span class="interface">Transaction </span>transaction = newSession.<span class="method">beginTransaction</span>();<br/><br/> <span class="interface">List</span><<span class="class">Reservation</span>> availableReservations = <span class="keyword">null</span>;<br/><br/> <span class="keyword">try </span>{<br/> <span class="interface">Query </span>query = newSession.<span class="method">createQuery</span>(<span class="string">"from </span><span class="class">Reservation</span><span class="string"> r where r.</span><span class="field">reserved</span><span class="string"> = false"</span>)<br/> .<span class="method">setLockMode</span>(<span class="string">"optimistic"</span>, <span class="class">LockMode</span>.<span class="static">OPTIMISTIC</span>)<br/> .<span class="method">setMaxResults</span>(<span class="parameter">count</span>);<br/><br/> availableReservations = query.<span class="method">list</span>();<br/><br/> <span class="comment">//There is no available reservations to reserve</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span><span class="keyword">if </span>(availableReservations.<span class="method">isEmpty</span>()) {<br/> <span class="keyword">throw new </span><span class="class">NoFreeReservationsException</span>();<br/> }<br/><br/> <span class="keyword">for </span>(<span class="class">Reservation </span>available : availableReservations) {<br/> available.<span class="method">reserve</span>(<span class="parameter">customerId</span>);<br/> newSession.<span class="method">save</span>(available);<br/> }<br/><br/> <span class="comment">//Commit can throw optimistic lock exception if it fails</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span>transaction.<span class="method">commit</span>();<br/><br/> <span class="comment">//Commit succeeded - this reference is used outside try-catch-finally block</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span>reserved = availableReservations;<br/><br/> } <span class="keyword">catch </span>(<span class="class">OptimisticLockException </span>| <span class="class">StaleObjectStateException </span>| <span class="class">HibernateOptimisticLockingFailureException </span><span class="parameter">e</span>) {<br/> <span class="static">log</span>.<span class="method">info</span>(<span class="string">"Optimistic lock exception occurred for customer {} and count {}: {} {}"</span>, <span class="parameter">customerId</span>, <span class="parameter">count</span>, <span class="parameter">e</span>.<span class="method">getClass</span>(), <span class="parameter">e</span>.<span class="method">getMessage</span>());<br/><br/> transaction.<span class="method">rollback</span>();<br/><br/> <span class="keyword">for </span>(<span class="class">Reservation </span>availableMsisdn : availableReservations) {<br/> newSession.<span class="method">evict</span>(availableMsisdn);<br/> }<br/> } <span class="keyword">finally </span>{<br/> newSession.<span class="method">close</span>();<br/> }<br/> <span class="comment">//Repeat until we reserve something</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span>} <span class="keyword">while </span>(reserved == <span class="keyword">null</span>);<br/><br/> <span class="static">log</span>.<span class="method">info</span>(<span class="string">"Successfully reserved {} reservations for customer {}"</span>, <span class="parameter">count</span>, <span class="parameter">customerId</span>);<br/><br/> <span class="comment">//Merge reserved entities to request session</span><span style="color:#696969;font-style:italic;"><br/></span><span style="color:#696969;font-style:italic;"> </span><span class="keyword">for </span>(<span class="class">Reservation </span>reservedMsisdn : reserved) {<br/> currentSession.<span class="method">merge</span>(reservedMsisdn);<br/> }<br/><br/> <span class="keyword">return </span>reserved;<br/> }<br/>}</code></pre>
<p>This code says it all. It tries to reserve some <code><span class="class">Reservation</span></code>s until it succeeds in a do-while loop. Main Request Session is not polluted and it achieves our goal.</p>
<p>I hope this example helps you in similar cases. It works as expected for a few months on our customer's production site and I recommend this solution.</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com0tag:blogger.com,1999:blog-5943570861711645804.post-83196126965705577312014-05-26T12:03:00.001+02:002014-05-26T12:20:45.316+02:00Meet Sputnik - static code analyser for Gerrit<h3>Sputnik runs Checkstyle, PMD and FindBugs for your Gerrit patchsets</h3>
<p>I am happy to announce a first release of <strong>Sputnik</strong>! It is a static code analyzer that runs Checkstyle, PMD and FindBugs for your Gerrit patchsets. Its main advantage over my previous project <a href="http://refaktor.blogspot.com/2013/12/sonar-gerrit-plugin-release.html" target="_blank">Sonar Gerrit plugin</a> is that Sputnik is a small, lightweight and standalone Java application. You don't need any other software to run it. It bundles Checkstyle, PMD and FindBugs jars within distribution zip.</p>
<h3>Workflow</h3>
<p>Sputnik is intended to use with Gerrit and Continous Integration server, i. e. Jenkins. It works like this:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg55y8jov0nY9HZRZ2yCcGUO8MdfzSrrNWdvz9Qs7Eb8QRoc1CXLnzY_kmSGuwCLSZMS_JyziS8e56u1MNEjsvAvNCbBUNVLh0HovW5OilyXhsetFu6GwpCBf4zsDqfT3gkx6ZZ3fXgCWU/s1600/Sputnik+and+Jenkins+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg55y8jov0nY9HZRZ2yCcGUO8MdfzSrrNWdvz9Qs7Eb8QRoc1CXLnzY_kmSGuwCLSZMS_JyziS8e56u1MNEjsvAvNCbBUNVLh0HovW5OilyXhsetFu6GwpCBf4zsDqfT3gkx6ZZ3fXgCWU/s1600/Sputnik+and+Jenkins+2.png" /></a></div>
<p>Your CI server is updated by ssh that a new patch is submitted to Gerrit. CI fetches this patch and builds a while project. After a build, CI server reports its result to Gerrit. It's time for Sputnik now.<p>
<p>Sputnik runs regardless of build result (you can change that in your CI configuration). Sputnik fetches patchset's file list from Gerrit over HTTP REST API. Then <strong>it runs an analysis only on these files!</strong> Even if your project is huge, analysis on several files takes only seconds. Sputnik collects comments from all three analysers: Checkstyle, PMD and FindBugs. It sends back all comments to Gerrit via HTTP REST API back. It's very simple and very fast!</p>
<h3>Installation and configuration</h3>
<p>First, you need to build <a href="https://github.com/TouK/sputnik" target="_blank">https://github.com/TouK/sputnik</a> master or download distribution zip from here: <a href="https://github.com/TouK/sputnik/releases/download/v1.0/sputnik-1.0.zip" target="_blank">sputnik-1.0.zip</a>. Go to you CI server and extract it to a directory of your choice. Remember that a user you run CI builds needs to have an access rights to this directory (in my case it's simply a <code>jenkins</code> user). Then you need to prepare your configuration file and write this file to the same directory as unzipped distribution. It is a simple Java properties file, which is pretty self-explanatory. Here is an example:</p>
<pre><code><span class="field">gerrit.host</span>=gerrit.yourcompany.com
<span class="field">gerrit.port</span>=8080
<span class="field">gerrit.username</span>=sputnik
<span class="field">gerrit.password</span>=Pa$$wo4d
<span class="field">checkstyle.enabled</span>=true
<span class="field">checkstyle.configurationFile</span>=/opt/jenkins/sputnik/checkstyle.xml
<span class="field">checkstyle.propertiesFile</span>=
<span class="field">pmd.enabled</span>=true
<span class="field">pmd.ruleSets</span>=/opt/jenkins/sputnik/pmd.xml
<span class="field">findbugs.enabled</span>=true
<span class="field">findbugs.includeFilter</span>=/opt/jenkins/sputnik/findbugs.xml
<span class="field">findbugs.excludeFilter</span>=</code></pre>
<p>Now you need to configure you CI server to actually run Sputnik after a build. It is very simple for Jenkins, just add a Post-Build Step. You can adjust if Sputnik runs only on successful build or for every build - use radio buttons for this:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLPvLsJ20Fd0Q6Gz9UmXp59bXlEpSk-lIiFMBtxM1t-LcdDmOzlp7zc0bZm2uV-s4qrBi3udGeLm3YmovH_T2-oTSfoUnGr5OauoXtAqO0s8doBnAzku_7fcHtWrumdsFPkDG1zv-zVfk/s1600/sputnik-jenkins.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLPvLsJ20Fd0Q6Gz9UmXp59bXlEpSk-lIiFMBtxM1t-LcdDmOzlp7zc0bZm2uV-s4qrBi3udGeLm3YmovH_T2-oTSfoUnGr5OauoXtAqO0s8doBnAzku_7fcHtWrumdsFPkDG1zv-zVfk/s1600/sputnik-jenkins.png" /></a></div>
<p>Last line with <code>exit 0</code> is a workaround for a clean exit, even if Sputnik fails for some reason. Exit 0 guarantees you that result of this step doesn't affect overall build result.</p>
<h3>Summary</h3>
<p>This is an example screenshot of Sputnik's comments:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBbn7U5Y6OSfzYagY3_45xajnkSJi2Cmu4-rjCjbNP8Nv0OBVTS5Xw2pfWn7wOsWdKEXRXKZXU8D7xBnSefF-_slac5joIIFEMB6yaGJL4kvA63cW-MGKzltHbdSeeBLGqwPQ7_f34QBg/s1600/sputnik-jenkins2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBbn7U5Y6OSfzYagY3_45xajnkSJi2Cmu4-rjCjbNP8Nv0OBVTS5Xw2pfWn7wOsWdKEXRXKZXU8D7xBnSefF-_slac5joIIFEMB6yaGJL4kvA63cW-MGKzltHbdSeeBLGqwPQ7_f34QBg/s1600/sputnik-jenkins2.png" /></a></div>
<p>Sputnik always reports +1 as a result. It can be lacking in some network and authorisation configuration. But it's open source so please submit issues and patches to its github page: <a href="https://github.com/TouK/sputnik" target="_blank">https://github.com/TouK/sputnik</a>. </p>
<p>Your feedback and pull requests are heartly welcome!</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com18tag:blogger.com,1999:blog-5943570861711645804.post-19782831118629974642013-12-20T13:23:00.001+01:002013-12-20T13:23:50.582+01:00Sonar Gerrit Plugin Release<h3>Initial release</h3>
<p>I am happy to announce a first release of my <a href="https://github.com/TouK/sonar-gerrit-plugin" target="_blank">Sonar Gerrit plugin</a>. This plugin reports Sonar violations on your patchsets to your Gerrit server. Sonar analyses full project, but only files included in patchset are commented on Gerrit. Please forward to project page for installation instructions.</p>
<p>This plugin is intended to use with <a href="https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger">Gerrit Trigger plugin</a> for Jenkins CI server. Together they provide a great tool for automatic static code analysis.</p>
<h3>How does it work?</h3>
<p>At the moment you push a patchset to Gerrit, Jenkins is notified with a ssh event. It fetches a code with a patchset and it builds your changes. It quits when build or tests fail.</p>
<p>But if it succeeds, Sonar analase your project in a post-build action. This is a place where my <a href="https://github.com/TouK/sonar-gerrit-plugin" target="_blank">Sonar Gerrit plugin</a> shines. It asks Gerrit for changed files before analysis and after Sonar analysis is finished, plugin reports comments on these files as a Gerrit reviewer. Currently plugin always reports +1 for Code Review, as it's still in development. However, you should always treat these comments as hints to improve, not as direct errors.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk9XiHuouMGx5ihxLp4FJybk8kWWAleQzoB2lrA0g8_o5-HujisDVea7SPpiz0uTKXxAl3fmXGrGfZcBmYmYY9Tt_6_UYvOVBOaibRHiPFr1sGwX40bxWpayH8psdjz2HtM6dUIjGLS6Y/s1600/Gerrit,+Jenkins,+Sonar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk9XiHuouMGx5ihxLp4FJybk8kWWAleQzoB2lrA0g8_o5-HujisDVea7SPpiz0uTKXxAl3fmXGrGfZcBmYmYY9Tt_6_UYvOVBOaibRHiPFr1sGwX40bxWpayH8psdjz2HtM6dUIjGLS6Y/s1600/Gerrit,+Jenkins,+Sonar.png" /></a></div>
<h3>Extras</h3>
<p>I've released also a second plugin: <a href="https://github.com/TouK/sonar-file-alerts-plugin" target="blank">Sonar File Alerts plugin</a>. This plugin raises alerts on file level in Sonar. It extends default behaviour, which raises alerts only at root project level. It is useful when you create alert rules in Sonar like <code>"Code Coverage < 60"</code>. Each file is checked against this rule!</p>
<p>If you use <a href="https://github.com/TouK/sonar-file-alerts-plugin" target="blank">Sonar File Alerts plugin</a> and an alert will be generated on some file, then a comment will be published on this file on Gerrit.</p>
<h3>Feedback</h3>
<p>Please provide a feedback on these plugins. Feel free to submit issues on github or comment. It's still an early stage so your input is very welcome!</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com2tag:blogger.com,1999:blog-5943570861711645804.post-55341941564612128972013-12-02T09:45:00.000+01:002013-12-02T09:47:19.105+01:00Custom SonarQube rules for Unit Tests<h1>I need a new rule</h1>
<p>In our project we use <a href="http://www.sonarqube.org/" target="_blank" imageanchor="1" style="" alt="SonarQube"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRUrFM4QUJ67pYBGvcGpTlLtx0TM9zuQUUF221F_uAq3lVZ3qgtsQht45-viP1Dfp1_MVlc4D41sULHmdCHKTDLwTil2suDBgSrI5_A22DIYfN-bXvCFDOl0FdPDHcEMSdOEtQugzf8AM/s1600/sonar.png" style="border: none; vertical-align: bottom; padding: 0 5px 0 5px"/></a> (formely Sonar) to manage our code quality. It is a great tool and I recommend everyone to set it up and read its reports.</p>
<p>Recently, we've agreed that it's better to use <a href="https://github.com/joel-costigliola/assertj-core">assertj</a> assertions in our unit tests than JUnit's. So I've decided to write a simple rule that checks if some of JUnit asserts <code>assertTrue</code>, <code>assertFalse</code>, <code>assertNull</code> and others are used. Then, I've discovered it's not so easy to do it with Sonar:</p>
<ul>
<li>only 10 code quality rules are applied to unit tests - they are in special repository PMD Unit Tests (<a href="http://jira.codehaus.org/browse/SONAR-1076?focusedCommentId=297506&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-297506" target="_blank">source</a>)</li>
<li>these 10 rules are disabled by default, you have to enable them by hand</li>
<li>you cannot add new rules to this group</li>
</ul>
<p>However, it turned out it is doable with a small tricks.</p>
<h1>Custom PMD Unit Tests rule tutorial</h1>
<p>Create your XPath expression by following this tutorial on <a href="http://pmd.sourceforge.net/pmd-5.0.5/howtowritearule.html" target="_blank">how to create custom PMD rule</a>. There is a visual editor to test your rules as you develop them - that's great. My XPath expression to avoid all JUnit assertions looks like this:</p>
<pre><code>//PrimaryPrefix/Name[@Image='assertEquals' or @Image='assertNull' or @Image='assertNotNull' or @Image='assertSame' or @Image='assertNotSame' or @Image='assertArrayEquals' or @Image='assertTrue' or @Image='assertFalse']</code></pre>
<p>Go to your Sonar installation, log in as an Administrator, head to Quality Profiles and select a profile that you use. Search for "xpath" and change Activation to <em>Any</em>. You should see two results like this:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7aIrOoNhuzr2u8tVfy8PJsddXJUACyFfilv5UNXPUsMYnxcN1SLngsbkkFxvBhLRP7FCn2v6RFWSDE2xfHZgTUshC63hS42npPfEcGrW6PgSev1wwgLfwL8AG_5edmAlzzXI64SRFLgo/s1600/sonar1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7aIrOoNhuzr2u8tVfy8PJsddXJUACyFfilv5UNXPUsMYnxcN1SLngsbkkFxvBhLRP7FCn2v6RFWSDE2xfHZgTUshC63hS42npPfEcGrW6PgSev1wwgLfwL8AG_5edmAlzzXI64SRFLgo/s1600/sonar1.jpg" /></a></div>
<p>Expand <strong>XPath rule template</strong> (dont' worry that it says it's deprecated) and then click <em>Copy rule</em>. Fill a form with message and XPath and save it. Then take a look at the bottom - you need an identifier of this rule:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIMPeBYy7c9fC298eznOMbzyWH7MFgNLRk7A7kukAtbRvn5WoJZLONX2PY5bcDCRDC5oqWu98GlJL5XMFca7n1hzXaNygbkS_QJernlBMIY342zcJJnAAHH9AgDA3lHH4a2tzTCrl0Uc0/s1600/sonar3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIMPeBYy7c9fC298eznOMbzyWH7MFgNLRk7A7kukAtbRvn5WoJZLONX2PY5bcDCRDC5oqWu98GlJL5XMFca7n1hzXaNygbkS_QJernlBMIY342zcJJnAAHH9AgDA3lHH4a2tzTCrl0Uc0/s1600/sonar3.jpg" /></a></div>
<p>You have created a PMD rule, now you need to move it to PMD Unit Tests group. Connect to Sonar's MySQL database. Search for your rule by key:</p>
<pre><code><span class="method">mysql></span> <span class="keyword">select</span> id, plugin_rule_key, plugin_name, parent_id, status <span class="keyword">from</span> rules <span class="keyword">where</span> plugin_rule_key=<span class="string">'XPathRule_1385721910'</span>;
+-----+----------------------+----------------+-----------+-------------+
| id | plugin_rule_key | plugin_name | parent_id | status |
+-----+----------------------+----------------+-----------+-------------+
| 903 | XPathRule_1385721910 | pmd | NULL | DEPRECATED |
+-----+----------------------+----------------+-----------+-------------+
<span class="field">1 row in set (0.00 sec)</span>
</code></pre>
<p>Update <code>plugin_name</code> and <code>status</code> (remember to use appropiate primary key for <code>id</code> column):</p>
<pre><code><span class="method">mysql></span> <span class="keyword">update</span> rules <span class="keyword">set</span> plugin_name=<span class="string">'pmd-unit-tests'</span>, status=<span class="string">'READY'</span> <span class="keyword">where</span> id=<span class="number">903</span>;
<span class="field">Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0</span></code></pre>
<p>There is one step left. Sonar will change this rule's status to <code>REMOVED</code> on restart due to his boot checks. You need to trick him and change <code>parent_id</code> to other's PMD Unit Tests rule. List all these rules and choose one's identifier.</p>
<pre><code>mysql> <span class="keyword">select</span> id, plugin_name, status <span class="keyword">from</span> rules <span class="keyword">where</span> plugin_name=<span class="string">'pmd-unit-tests'</span>;
+-----+----------------+---------+
| id | plugin_name | status |
+-----+----------------+---------+
| 775 | pmd-unit-tests | READY |
| 776 | pmd-unit-tests | READY |
| 777 | pmd-unit-tests | READY |
| 778 | pmd-unit-tests | READY |
| 779 | pmd-unit-tests | READY |
| 780 | pmd-unit-tests | READY |
| 781 | pmd-unit-tests | READY |
| 782 | pmd-unit-tests | READY |
| 783 | pmd-unit-tests | READY |
| 784 | pmd-unit-tests | READY |
| 903 | pmd-unit-tests | READY |
+-----+----------------+---------+
<span class="field">11 rows in set (0.00 sec)</span></code></pre>
<p>Choose any <code>id</code> you like, let's say 775 and apply it as <code>parent_id</code> to your newly created rule:</p>
<pre><code>mysql> <span class="keyword">update</span> rules <span class="keyword">set</span> parent_id=<span class="number">775</span> <span class="keyword">where</span> id=<span class="number">903</span>;
<span class="field">Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0</span></code></pre>
<p>Go to your Quality profile and make sure your rule is active! Check it twice, it's easy to forget that step. It's all set up, enjoy your analysis!</p>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com3tag:blogger.com,1999:blog-5943570861711645804.post-19690382426383914102013-08-01T11:54:00.000+02:002014-03-25T16:10:07.753+01:00Error generating web.xml file with IntelliJ IDEA<p>If you use IntelliJ IDEA for your Grails development you might encounter this error running integration tests:</p>
<pre><code>Error Error generating web.xml file (Use --stacktrace to see the full trace)</code></pre>
<p>The reason for this is that IDEA adds classpath by default on creating integration test run configuration. Unfortunately, sometimes it causes strange errors like this one. Follow these steps to resolve:</p>
<ol>
<li>Open Run → Edit Configurations... (or press <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>F10</kbd>)</li>
<li>Select your configuration that fails</li>
<li>Uncheck <strong>Add --classpath</strong> checkbox</li>
<li>You are done! Run.</li>
</ol>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com1tag:blogger.com,1999:blog-5943570861711645804.post-16011686370001093422013-07-09T16:19:00.000+02:002013-07-10T10:30:27.778+02:00Local Graphite installation on CentOS 5.5 howto<h3>Feature request</h3>
<p>Our client called:<br /><em>
- "I want something to monitor my application!"<br />
- "Ok, let's use JMX, we have plenty of stats exposed there already."<br />
- "Fine, but I want something fancy!"<br />
- "Ok, let's install <a href="http://graphite.wikidot.com/" target="_blank">Graphite</a>, take a look at screenshots!"<br />
- "Excellent! Use our testing CentOS machine for this."<br />
- "Ok, erm... wait, nooooo! We have no root access there, there is no internet access and we can't install anything!!!"<br />
- "(hangup click)"</em></p>
<h3>Setup</h3>
<p>There I was, standing alone, looking for help...</p>
<ul><strong>My scenario:</strong>
<li>no internet access</li>
<li>only user account, no root account</li>
<li>gcc and make installed</li>
<li>some libraries missing</li>
<li>no development packages for installed libraries</li>
</ul>
<ul style="margin-top: 15px"><strong>My goals:</strong>
<li>install libraries to $HOME</li>
<li>install Graphite and stuff to $HOME/graphite</li>
</ul>
<h3 style="margin-top: 15px">Solution</h3>
<p>It took me a few days, but I've managed to install Graphite locally. Here is a gist for a sake of documentation and for others that may need it.</p>
<pre><code><a href="https://gist.github.com/SpOOnman/5957589" target="_blank">https://gist.github.com/SpOOnman/5957589</a></code></pre>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com0tag:blogger.com,1999:blog-5943570861711645804.post-77146556031893451992013-06-05T09:24:00.000+02:002013-06-05T09:24:10.105+02:00Simple trick to DRY your Grails controller<p>Grails controllers are not very DRY. It's easy to find duplicated code fragments in default generated controller. Take a look at code sample below. It is duplicated <strong>four</strong> times in <code><span class="method">show</span></code>, <code><span class="method">edit</span></code>, <code><span class="method">update</span></code> and <code><span class="method">delete</span></code> actions:</p>
<pre><code><span class="keyword">class</span> <span class="class">BookController</span> {
<span class="keyword">def</span> <span class="method">show</span>() {
<span class="keyword">def</span> bookInstance = <span class="class">Book</span>.<span class="static">get</span>(<span class="property">params</span>.<span class="field">id</span>)
<span class="keyword">if</span> (!bookInstance) {
<span class="property">flash</span>.<span class="field">message</span> = <span class="method">message</span>(<span class="field">code</span>: <span class="string">'default.not.found.message'</span>, <span class="field">args</span>: [<span class="method">message</span>(<span class="field">code</span>: <span class="string">'</span><span class="string">book.label</span><span class="string">'</span>, <span class="field">default</span>: <span class="string">'Book'</span>), <span class="property">params</span>.<span class="field">id</span>])
<span class="method">redirect</span>(<span class="field">action</span>: <span class="string">"list"</span>)
<span class="keyword">return</span>
}
[<span class="field">bookInstance</span>: bookInstance]
}
}</code></pre>
<h3>Why is it duplicated?</h3>
<p>There is a reason for that duplication, though. If you move this snippet to a method, it can redirect to <code><span class="string">"list"</span></code> action, but it can't prevent controller from further execution. After you call <code><span class="method">redirect</span></code>, response status changes to 302, but after method exits, controller still runs subsequent code.</p>
<h3>Solution</h3>
<p>At <a href="http://touk.pl" target="_blank">TouK</a> we've implemented a simple trick to resolve that situation:</p>
<ol><li>wrap everything with a simple <code><span class="method">withStoppingOnRender</span></code> method,</li>
<li>whenever you want to render or redirect <strong>AND</strong> stop controller execution - throw <code><span class="class">EndRenderingException</span></code>.</li></ol>
<p>We call it <em>Big Return</em> - return from a method and return from a controller at once. Here is how it works:</p>
<pre><code><span class="keyword">class</span> <span class="class">BookController</span> {
<span class="keyword">def</span> <span class="method">show</span>(<span class="class">Long</span> <span class="parameter">id</span>) {
<span class="method">withStoppingOnRender</span> {
<span class="class">Book</span> bookInstance = <span class="class">Book</span>.<span class="static">get</span>(<span class="parameter">id</span>)
<span class="method">validateInstanceExists</span>(bookInstance)
[<span class="field">bookInstance</span>: bookInstance]
}
}
<span class="keyword">protected</span> <span class="class">Object</span> <span class="method">withStoppingOnRender</span>(<span class="class">Closure</span> <span class="parameter">closure</span>) {
<span class="keyword">try</span> {
<span class="keyword">return</span> <span class="parameter">closure</span>.<span class="method">call</span>()
} <span class="keyword">catch</span> (<span class="class">EndRenderingException</span> <span class="parameter">e</span>) {}
}
<span class="keyword">private</span> <span class="keyword">void</span> <span class="method">validateInstanceExists</span>(<span class="class">Book</span> <span class="parameter">instance</span>) {
<span class="keyword">if</span> (!<span class="parameter">instance</span>) {
<span class="property">flash</span>.<span class="field">message</span> = <span class="method">message</span>(<span class="field">code</span>: <span class="string">'default.not.found.message'</span>, <span class="field">args</span>: [<span class="method">message</span>(<span class="field">code</span>: <span class="string">'book.label'</span>, <span class="field">default</span>: <span class="string">'Book'</span>), <span class="property">params</span>.<span class="field">id</span>])
<span class="method">redirect</span>(<span class="field">action</span>: <span class="string">"list"</span>)
<span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">EndRenderingException</span>()
}
}
}
<span class="keyword">class</span> <span class="class">EndRenderingException</span> <span class="keyword">extends</span> <span class="class">RuntimeException</span> {}</code></pre>
<h3>Example usage</h3>
<p>For simple CRUD controllers, you can use this solution and create some <code><span class="class">BaseController</span></code> class for your controllers. We use <code><span class="method">withStoppingOnRender</span></code> in every controller so code doesn't look like a spaghetti, we follow DRY principle and code is self-documented. Win-win-win! Here is a more complex example:</p>
<pre><code><span class="keyword">class</span> <span class="class">DealerController</span> {
<span class="annotation">@Transactional</span>
<span class="keyword">def</span> <span class="method">update</span>() {
<span class="method">withStoppingOnRender</span> {
<span class="class">Dealer</span> dealerInstance = <span class="class">Dealer</span>.<span class="static">get</span>(<span class="property">params</span>.<span class="field">id</span>)
<span class="method">validateInstanceExists</span>(dealerInstance)
<span class="method">validateAccountInExternalService</span>(dealerInstance)
<span class="method">checkIfInstanceWasConcurrentlyModified</span>(dealerInstance, <span class="property">params</span>.<span class="field">version</span>)
dealerInstance.<span class="property">properties</span> = <span class="property">params</span>
<span class="method">saveUpdatedInstance</span>(dealerInstance)
<span class="method">redirectToAfterUpdate</span>(dealerInstance)
}
}
}</code></pre>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com7tag:blogger.com,1999:blog-5943570861711645804.post-45426346282160965482013-05-07T11:13:00.000+02:002013-05-07T11:13:39.902+02:00New HTTP Logger Grails plugin<p>I've wrote a new Grails plugin - <a href="http://grails.org/plugins/httplogger" target="_blank">httplogger</a>. It logs:</p>
<ul><li>request information (url, headers, cookies, method, body),</li>
<li>grails dispatch information (controller, action, parameters),</li>
<li>response information (elapsed time and body).</li></ul>
<p>It is mostly useful for logging your REST traffic. Full HTTP web pages can be huge to log and generally waste your space. I suggest to map all of your REST controllers with the same path in <code><span class="class">UrlMappings</span></code>, e.g. <code>/rest/</code> and configure this plugin with this path.</p>
<p>Here is some simple output just to give you a taste of it.</p>
<pre><code>17:16:00,331 INFO filters.LogRawRequestInfoFilter - << #1 GET http://localhost:8080/riddle/rest/index?username=admin&search=foo
17:16:00,340 INFO filters.LogRawRequestInfoFilter - << #1 headers Cookie: 'JSESSIONID=DF4EA5725AC4A4990281BD96963739B0; splashShown1.6=1', Accept-Language: 'en-US,en;q=0.8,pl;q=0.6', X-MyHeader: 'null'
17:16:00,342 INFO filters.LogGrailsUrlsInfoFilter - << #1 dispatched to rest/index with parsed params [username:[admin], search:[foo]].
17:16:00,731 INFO filters.LogOutputResponseFilter - >> #1 returned 200, took 405 ms.
17:16:00,745 INFO filters.LogOutputResponseFilter - >> #1 responded with '{count:0}'</code></pre>
<pre><code>17:18:55,799 INFO filters.LogRawRequestInfoFilter - << #2 POST http://localhost:8080/riddle/rest/login
17:18:55,799 INFO filters.LogRawRequestInfoFilter - << #2 headers Cookie: 'JSESSIONID=DF4EA5725AC4A4990281BD96963739B0; splashShown1.6=1', Accept-Language: 'en-US,en;q=0.8,pl;q=0.6', X-MyHeader: 'null'
17:18:55,800 INFO filters.LogRawRequestInfoFilter - << #2 body: 'username=admin&password=password'
17:18:55,801 INFO filters.LogOutputResponseFilter - >> #2 returned 404, took 3 ms.
17:18:55,802 INFO filters.LogOutputResponseFilter - >> #2 responded with ''</code></pre>
<p>Official plugin information can be found on Grails plugins website here: <a href="http://grails.org/plugins/httplogger" target="_blank">http://grails.org/plugins/httplogger</a> or you can browse code on github: <a href="https://github.com/TouK/grails-httplogger" target="_blank">TouK/grails-httplogger</a>.</p>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com0tag:blogger.com,1999:blog-5943570861711645804.post-78648301209797695732013-01-14T22:33:00.000+01:002013-01-15T10:02:07.792+01:00How to keep session in HttpBuilder with cookies<p>In my real-world scenario I have a REST service for AJAX purposes. It renders data series for graphs. I want to test it with groovy's excellent <a href="http://groovy.codehaus.org/modules/http-builder/" target="_blank">HttpBuilder</a>. There is a problem though - these requests are only available for already logged in users.</p>
<p>In this post I present a complete solution to maintain a session state between <a href="http://groovy.codehaus.org/modules/http-builder/" target="_blank">HttpBuilder</a>'s requests.</p>
<h3>Session in HttpBuilder</h3>
<p>First of all a quick reminder about session. Session is a simulation of state for HTTP requests, which are stateless by its nature. Once you log in you receive a unique cookie (one or more) that identifies you for sequential requests. Every time you send request you send this cookie along. This way server recognizes you and matches you to your session, which is kept on server. Cookie gets invlid once you log out or it times out, for example after 20 minutes of inactivity. Next time you visit a page you get a new, unique cookie.</p>
<p>In order to keep session alive in HttpBuilder I need to:</p>
<ol>
<li>log in to my Grails application</li>
<li>receive a JSESSIONID cookie in response</li>
<li>store that cookie and send it along with every subsenquential request</li>
</ol>
<p>I've created <code><span class="method">RestConnector</span></code> class that wraps up HttpBuilder. It's main improvement is that it keeps received cookie in a list.</p>
<pre><code><span class="keyword">package</span> eu.spoonman.connectors.RestConnector
<span class="keyword">import</span> groovyx.net.http.<span class="class">Method</span>
<span class="keyword">import</span> groovyx.net.http.<span class="class">ContentType</span>
<span class="keyword">import</span> groovyx.net.http.<span class="class">HTTPBuilder</span>
<span class="keyword">import</span> groovyx.net.http.<span class="class">HttpResponseDecorator</span>
<span class="keyword">class</span> <span class="class">RestConnector</span> {
<span class="keyword">private</span> <span class="class">String</span> <span class="field">baseUrl</span>
<span class="keyword">private</span> <span class="class">HTTPBuilder</span> <span class="field">httpBuilder</span>
<span class="keyword">private</span> <span class="class">List</span><<span class="class">String</span>> <span class="field">cookies</span>
<span class="method">RestConnector</span>(<span class="class">String</span> <span class="parameter">url</span>) {
<span class="keyword">this</span>.<span class="field">baseUrl</span> = <span class="parameter">url</span>
<span class="keyword">this</span>.<span class="field">httpBuilder</span> = <span class="method">initializeHttpBuilder</span>()
<span class="keyword">this</span>.<span class="field">cookies</span> = []
}
<span class="keyword">public</span> <span class="keyword">def</span> <span class="method">request</span>(<span class="class">Method</span> <span class="parameter">method</span>, <span class="class">ContentType</span> <span class="parameter">contentType</span>, <span class="class">String</span> <span class="parameter">url</span>, <span class="class">Map</span><<span class="class">String</span>, <span class="class">Serializable</span>> <span class="parameter">params</span>) {
<span class="method">debug</span>(<span class="string">"Send </span>$<span class="parameter">method</span><span class="string"> request to </span>${<span class="keyword">this</span>.<span class="field">baseUrl</span>}$<span class="parameter">url</span><span class="string">: </span>$<span class="parameter">params</span><span class="string">"</span>)
<span class="field">httpBuilder</span>.<span class="method">request</span>(<span class="parameter">method</span>, <span class="parameter">contentType</span>) { <span class="parameter">request</span> ->
<span class="property">uri</span>.path = <span class="parameter">url</span>
<span class="property">uri</span>.query = <span class="parameter">params</span>
<span class="property">headers</span>[<span class="string">'Cookie'</span>] = <span class="field">cookies</span>.<span class="method">join</span>(<span class="string">';'</span>)
}
}
<span class="keyword">private</span> <span class="class">HTTPBuilder</span> <span class="method">initializeHttpBuilder</span>() {
<span class="keyword">def</span> httpBuilder = <span class="keyword">new</span> <span class="class">HTTPBuilder</span>(<span class="field">baseUrl</span>)
httpBuilder.<span class="property">handler</span>.<span class="field">success</span> = { <span class="class">HttpResponseDecorator</span> <span class="parameter">resp</span>, <span class="parameter">reader</span> ->
<span class="parameter">resp</span>.<span class="method">getHeaders</span>(<span class="string">'Set-Cookie'</span>).<span class="method">each</span> {
<span class="comment">//[Set-Cookie: JSESSIONID=E68D4799D4D6282F0348FDB7E8B88AE9; Path=/frontoffice/; HttpOnly]</span>
<span class="class">String</span> cookie = <span class="parameter">it</span>.value.<span class="method">split</span>(<span class="string">';'</span>)[<span class="number">0</span>]
<span class="method">debug</span>(<span class="string">"Adding cookie to collection: </span>$cookie<span class="string">"</span>)
<span class="field">cookies</span>.<span class="method">add</span>(cookie)
}
<span class="method">debug</span>(<span class="string">"Response: </span>${<span class="parameter">reader</span>}<span class="string">"</span>)
<span class="keyword">return</span> <span class="parameter">reader</span>
}
<span class="keyword">return</span> httpBuilder
}
<span class="keyword">private</span> <span class="method">debug</span>(<span class="class">String</span> <span class="parameter">message</span>) {
<span class="class">System</span>.<span class="static">out</span>.<span class="method">println</span>(<span class="parameter">message</span>) <span class="comment">//for </span><span class="comment">Gradle</span>
}
}
</code></pre>
<p>A few things to notice in a class above. Constructor sets base URL and creates HttpBuilder instance that can be reused. Next, there is a handler on successful request that checks if I receive any cookie. It adds received cookies to list. Finally, there is a <code><span class="method">request</span></code> method that calls <code><span class="class">HttpBuilder</span>#<span class="method">request</span></code> but it adds cookies to HTTP headers so server can recognize me as a logged in user.</p>
<p>Sending cookies with every request is a core component in here. It simulates browser's behavior and maintains session.</p>
<h3>How to use it?</h3>
<p>I will show you how to use this utility class it in Spock test below. It is fairly simple.</p>
<p>First I login to my application and I ensure that I receive a cookie in return, which is equivalent to being logged in. Then I send a request with that cookie sent in HTTP header. This is a Spock test that implements it:</p>
<pre><code><span class="keyword">package</span> eu.spoonman.specs.rest
<span class="keyword">import</span> eu.spoonman.connectors.RestConnector.<span class="class">RestConnector</span>
<span class="keyword">import</span> groovyx.net.http.<span class="class">ContentType</span>
<span class="keyword">import</span> groovyx.net.http.<span class="class">Method</span>
<span class="keyword">import</span> <span class="annotation">spock.lang.Shared</span>
<span class="keyword">import</span> spock.lang.<span class="class">Specification</span>
<span class="keyword">import</span> <span class="annotation">spock.lang.Stepwise</span>
<span class="annotation">@Stepwise</span>
<span class="keyword">class</span> <span class="class">RestChartSpec</span> <span class="keyword">extends</span> <span class="class">Specification</span> {
<span class="annotation">@Shared</span>
<span class="class">RestConnector</span> <span class="field">restConnector</span>
<span class="keyword">def</span> <span class="method">setupSpec</span>() {
<span class="field">restConnector</span> = <span class="keyword">new</span> <span class="class">RestConnector</span>(<span class="string">'http://localhost:8080'</span>)
}
<span class="keyword">def</span> <span class="method">"should login as test"</span>() {
given:
<span class="class">Map</span> params = [<span class="field">j_username</span>: <span class="string">'test'</span>, <span class="field">j_password</span>: <span class="string">'test'</span>]
when:
<span class="field">restConnector</span>.<span class="method">request</span>(<span class="class">Method</span>.<span class="static">POST</span>, <span class="class">ContentType</span>.<span class="static">ANY</span>, <span class="string">'/frontoffice/j_spring_security_check'</span>, params)
then:
!(<span class="field">restConnector</span>.<span class="property">cookies</span>.<span class="property">empty</span>)
}
<span class="keyword">def</span> <span class="method">"should allow access to chart data series"</span>() {
given:
<span class="class">Map</span> params = [<span class="field">days</span>: <span class="number">14</span>]
when:
<span class="class">Map</span> result = <span class="field">restConnector</span>.<span class="method">request</span>(<span class="class">Method</span>.<span class="static">POST</span>, <span class="class">ContentType</span>.<span class="static">JSON</span>, <span class="string">"frontoffice/chart/series"</span>, params)
then:
result != <span class="keyword">null</span>
result.<span class="field">series</span>.size() > <span class="number">0</span>
}
}</code></pre>
<p>I create a new <code><span class="class">RestConnector</span></code> instance in <code><span class="method">setupSpec</span></code> with my application's base URL. Please notice that it has <code><span class="annotation">@Shared</span></code> annotation so it's shared between tests.</p>
<p><code><span class="annotation">@Stepwise</span></code> is crucial annotation for this specification. It means that Spock executes tests exactly in order they're defined. I need to ensure that login is executed first. I also need to assert that I receive a cookie and list is not empty. I could move this step into <code><span class="method">setupSpec</span></code> method too, but I prefer it to be a first test in a specification.</p>
<p>Second test is always executed after login thus it sends cookies within request headers. This is exactly what I wanted to achieve.</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com12tag:blogger.com,1999:blog-5943570861711645804.post-92122185583532334022012-11-28T21:08:00.000+01:002013-01-09T10:11:28.767+01:00Use XMLs not groovy scripts with db migration plugin!<p>I have 48 domain classes in my Grails 2.1 project and I use Grails Database Migration Plugin 1.2 for a database management. Recently I've noticed that it becomes terribly slow when running application, even if there are no changes to be applied.</p>
<p>I switched do debug logging level for <code>liquibase</code> package and I found that it takes <strong>about 15 seconds</strong> to parse <code>changelog.groovy</code> and 20 files that were included in it!</p>
<h3>Prepare benchmark</h3>
<p>I couldn't belive it so I've created two new clean changelogs:</p>
<pre><code><span class="keyword">$</span> grails dbm-generate-changelog changelog.groovy
<span class="keyword">$</span> grails dbm-generate-changelog changelog.xml</code></pre>
<p>Both of these changelogs contain 229 change sets. It is enough that you can benchmark parsers for them. Two parsers in question are:</p>
<ul>
<li><code>grails.plugin.databasemigration.<span class="class">GrailsChangeLogParser</span></code></li>
<li><code>liquibase.parser.core.xml.<span class="class">XMLChangeLogSAXParser</span></code></li>
</ul>
<p>I need to modify a line in my Config.groovy and switch <code>changelog.groovy</code> with <code>changelog.xml</code> for a second test:</p>
<pre><code>grails.plugin.databasemigration.updateOnStart = <span class="keyword">true</span>
grails.plugin.databasemigration.updateOnStartFileNames = ["<span class="string">changelog.groovy"</span>]
<span class="comment">// grails.plugin.databasemigration.updateOnStartFileNames = ["changelog.xml"]</span></code></pre>
<noscript><pre><code>grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ["changelog-all.groovy"]
// grails.plugin.databasemigration.updateOnStartFileNames = ["changelog-all.xml"]</code></pre></noscript>
<h3>Profile with JProfiler</h3>
<p>I want to profile execution time. I use <a href="http://www.ej-technologies.com/products/jprofiler/overview.html" target="_blank">JProfiler</a> from ej-technologies to measure execution times. Please notice that I don't want to benchmark SQL queries performed by liquibase. I am only focused on <code><span class="method">parse</span></code> method of these two classes.</p>
<p>Here's how I set up JProfiler:</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0NKgoYNubcm46g9aFWGIB3zDpr1FJMpb4HgsdAUPwG4h2CT2dbCkE9-DWtrDm7KG8KmjMpKQ_8YMsbhThktPwOpva_F_AmuzRf7IflTNMd2gnGs1FwFyuKM6T_2dHjaOA6eBHZKIwtC0/s1600/liquibase1.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="302" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0NKgoYNubcm46g9aFWGIB3zDpr1FJMpb4HgsdAUPwG4h2CT2dbCkE9-DWtrDm7KG8KmjMpKQ_8YMsbhThktPwOpva_F_AmuzRf7IflTNMd2gnGs1FwFyuKM6T_2dHjaOA6eBHZKIwtC0/s320/liquibase1.jpg" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD5V-rDs51lpTY5Kq_dkZrHaBipqiLx4Oug18q9yw9nUIr6X9dKd_wedVSOo7v26TqrxqLQSAXcCGqDTNlshcfBrRd0S-W482jfKK-aecmBnTZQyi2uUonuTXnTTdq3CFVdrN3ca6iu8c/s1600/liquibase2.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="302" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD5V-rDs51lpTY5Kq_dkZrHaBipqiLx4Oug18q9yw9nUIr6X9dKd_wedVSOo7v26TqrxqLQSAXcCGqDTNlshcfBrRd0S-W482jfKK-aecmBnTZQyi2uUonuTXnTTdq3CFVdrN3ca6iu8c/s320/liquibase2.jpg" /></a></div>
<p>I switch to CPU Views - Method statistics and I click "Record". Here are results for both parsers:<p>
<h3>Results for changelog.groovy</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEwnpk3MRbgqLhArGwz41alWLC0LTwyj7_3LpLr1MuaCrYWrIMwHgzMFcAeQhejgk6GygnvxfENPPVZw4qrLNVeY5Fvlxd6-vt_XgB7Ep1PW3a5FRwXEVwsAcE0KD13_wMfCPam1QWrK0/s1600/liquibase4.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="230" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEwnpk3MRbgqLhArGwz41alWLC0LTwyj7_3LpLr1MuaCrYWrIMwHgzMFcAeQhejgk6GygnvxfENPPVZw4qrLNVeY5Fvlxd6-vt_XgB7Ep1PW3a5FRwXEVwsAcE0KD13_wMfCPam1QWrK0/s400/liquibase4.jpg" /></a></div>
<h3>Results for changelog.xml</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyzIb1wPfKIgm1e4YfBxlXcqZCu6JjtJmCIvWEwRnBEwkzOgbsxChUSkVg41qYB5Mi3a6Zk6GTLGWpohcrCRHuCXTCC4uciOPqby_XXdVm-BPSi2i7kqjcyASBSe5ZYCCI6JJUp5r2u38/s1600/liquibase5.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="230" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyzIb1wPfKIgm1e4YfBxlXcqZCu6JjtJmCIvWEwRnBEwkzOgbsxChUSkVg41qYB5Mi3a6Zk6GTLGWpohcrCRHuCXTCC4uciOPqby_XXdVm-BPSi2i7kqjcyASBSe5ZYCCI6JJUp5r2u38/s400/liquibase5.jpg" /></a></div>
<h3>Analysis</h3>
<p>My assumptions were correct: 8 339 ms vs 139 ms. <strong>Parsing XML is 60 times faster!</strong> I want to jump and sing: "I switch to XML now!", but I have some concerns. I have a production database that I need to be compatible with. And I should rewrite my all groovy changelog files by hand. So it's not so trivial and it's a time consuming and error prone task.</p>
<p>So as much as I want to switch to XML now, I won't. But if you start your adventure with database migration plugin today I have an advice for you: <strong>use XML if you start from scratch</strong>. </p>
<p>For now I've just submitted a new JIRA issue - <a href="http://jira.grails.org/browse/GPDATABASEMIGRATION-107" target="_blank">GrailsChangeLogParser - parse method is very slow</a> and I hope it can be greatly improved.</p>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com2tag:blogger.com,1999:blog-5943570861711645804.post-52492075476374609772012-11-21T15:31:00.000+01:002013-01-10T11:29:37.913+01:00Grails render as JSON catch<p>One of a reasons your controller doesn't render a proper response in JSON format might be wrong package name that you use. It is easy to overlook. Import are on top of a file, you look at your code and everything seems to be fine. Except response is still not in JSON format.</p>
<p>Consider this simple controller:</p>
<pre><code><span class="keyword">class</span> <span class="class">RestJsonCatchController</span> {
<span class="keyword">def</span> <span class="method">grailsJson</span>() {
<span class="method">render</span>([<span class="field">first</span>: <span class="string">'foo'</span>, <span class="field">second</span>: <span class="number">5</span>] <span class="keyword">as</span> grails.converters.<span class="class">JSON</span>)
}
<span class="keyword">def</span> <span class="method">netSfJson</span>() {
<span class="method">render</span>([<span class="field">first</span>: <span class="string">'foo'</span>, <span class="field">second</span>: <span class="number">5</span>] <span class="keyword">as</span> net.sf.json.<span class="class">JSON</span>)
}
}
</code></pre>
<p>And now, with finger crossed... We have a winner!</p>
<pre><code><span class="keyword">$</span> curl localhost:8080/example/restJsonCatch/grailsJson
{"first":"foo","second":5}
<span class="keyword">$</span> curl localhost:8080/example/restJsonCatch/netSfJson
{first=foo, second=5}
</code></pre>
<p>As you can see only <code>grails.converters.<span class="class">JSON</span></code> converts your response to JSON format. There is no such converter for <code>net.sf.json.<span class="class">JSON</span></code>, so Grails has no converter to apply and it renders Map normally.</p>
<p><strong>Conclusion: always carefully look at your imports if you're working with JSON in Grails!</strong></p>
<p><strong>Edit:</strong> Burt suggested that this is a bug. I've submitted JIRA issue here: <a href="http://jira.grails.org/browse/GRAILS-9622">GRAILS-9622 render as class that is not a codec should throw exception</a></p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com7tag:blogger.com,1999:blog-5943570861711645804.post-45578506647212533192012-10-18T13:00:00.002+02:002012-11-21T15:32:19.729+01:00Inconsistent Dependency Injection to domains with Grails <p>I've encountered strange behavior with a domain class in my project: services that should be injected were null. I've became suspicious as why is that? Services are injected properly in other domain classes so why this one is different?</p>
<h3>Constructors experiment</h3>
<p>I've created an experiment. I've created empty LibraryService that should be injected and Book domain class like this:</p>
<script src="https://gist.github.com/3910934.js?file=Book.groovy"></script>
<noscript><pre><code>class Book {
def libraryService
String author
String title
int pageCount
Book() {
println("Finished constructor Book()")
}
Book(String author) {
this()
this.@author = author
println("Finished constructor Book(String author)")
}
Book(String author, String title) {
super()
this.@author = author
this.@title = title
println("Finished constructor Book(String author, String title)")
}
Book(String author, String title, int pageCount) {
this.@author = author
this.@title = title
this.@pageCount = pageCount
println("Finished constructor Book(String author, String title, int pageCount)")
}
void logInjectedService() {
println(" Service libraryService is injected? -> $libraryService")
}
}</code></pre>
</noscript>
<script src="https://gist.github.com/3910934.js?file=LibraryService.groovy"></script>
<noscript><pre><code>class LibraryService {
def serviceMethod() {
}
}</code></pre></noscript>
<p><code>Book</code> has 4 explicit constructors. I want to check which constructor is injecting dependecies. This is my method that constructs <code>Book</code> objects and I called it in controller:
<script src="https://gist.github.com/3910934.js?file=BookController.groovy"></script>
<noscript><pre><code>class BookController {
def index() {
constructAndExamineBooks()
}
static constructAndExamineBooks() {
println("Started constructAndExamineBooks")
Book book1 = new Book().logInjectedService()
Book book2 = new Book("foo").logInjectedService()
Book book3 = new Book("foo", 'bar').logInjectedService()
Book book4 = new Book("foo", 'bar', 100).logInjectedService()
Book book5 = new Book(author: "foo", title: 'bar')
println("Finished constructor Book(Map params)")
book5.logInjectedService()
}
}</code></pre></noscript>
<h3>Analysis</h3>
<p>Output looks like this:</p>
<script src="https://gist.github.com/3910934.js?file=output.txt"></script>
<noscript><pre><code>Started constructAndExamineBooks
Finished constructor Book()
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2
Finished constructor Book()
Finished constructor Book(String author)
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2
Finished constructor Book(String author, String title)
Service libraryService is injected? -> null
Finished constructor Book(String author, String title, int pageCount)
Service libraryService is injected? -> null
Finished constructor Book()
Finished constructor Book(Map params)
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2</code></pre></noscript>
<p>What do we see?</p>
<ol>
<li><h4 style="float:right;color:#060">✔</h4>Empty constructor injects dependencies.</li>
<li style="clear:both"><h4 style="float:right;color:#060">✔</h4>Constructor that invokes empty constructor explicitly injects dependencies.</li>
<li style="clear:both"><h4 style="float:right;color:#600">✘</h4>Constructor that invokes parent's constructor explicitly <strong>does not inject dependencies.</strong></li>
<li style="clear:both"><h4 style="float:right;color:#600">✘</h4>Constructor without any explicit call declared <strong>does not call empty constructor</strong> thus <strong>it does not inject dependencies</strong>.
<li style="clear:both"><h4 style="float:right;color:#060">✔</h4>Constructor provied by Grails with a map as a parameter invokes empty constructor and injects dependencies.</li>
</ol>
<h3>Conclusion</h3>
<p><strong>Always explicitily invoke empty constructor in your Grail domain classes to ensure Dependency Injection!</strong> I didn't know until today either!</p>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com10tag:blogger.com,1999:blog-5943570861711645804.post-91395497919753604522012-09-20T14:39:00.000+02:002013-01-10T22:45:55.213+01:00Classloader problem with Java 7 and WebServices in Grails<p>Our Grails 2.1 application communicates with external SOAP WebServices. It worked fine as we follow Software Guy's advices from <a href="http://asoftwareguy.com/2012/02/25/web-service-clients-where-grails-lost-its-mojo/" target="_blank">this blog post</a>.</p>
<p>Recently, our client required new functionality - export to Excel. We've used <a href="http://poi.apache.org/" target="blank">Apache POI</a> libraries for export. <strong>And our web service communication died.</strong> All it gave us was:</p>
<pre><code>Caused by: java.lang.LinkageError: loader constraint violation: when resolving field "DATETIME" the class loader (instance of org/codehaus/groovy/grails/cli/support/GrailsRootLoader) of the referring class, javax/xml/datatype/DatatypeConstants, and the class loader (instance of <bootloader>) for the field's resolved type, ants, have different Class objects for that type</code></pre>
<p>This message is strange, LinkageError can give you creeps. But read carefully: <strong>resolved type, ants</strong>? Something is definitely wrong here. After many searches it turned out that Java 7 already contains some conflicting classes from stax-api.jar. To solve this problem there are two thing you need to do:</p>
<ol>
<li>Ensure that your jaxws-rt dependency is runtime, not compile!
<pre><code>// http://asoftwareguy.com/2012/02/25/web-service-clients-where-grails-lost-its-mojo/
// Do not remove this dependency. Web services need this to work flawlessly.
runtime ('com.sun.xml.ws:jaxws-rt:2.1.4')</code></pre>
</li>
<li>Create dependency report (<code>grails dependency-report</code>), search and exclude all stax-api dependencies other than jaxws-rt like this example:
<pre><code>compile (<span class="string">'org.apache.poi:poi-ooxml-3.7'</span>) {
excludes <span class="string">'stax-api'</span>
}
compile (<span class="string">'org.apache.poi:poi-ooxml-schemas:3.7'</span>) {
excludes <span class="string">'stax-api'</span>
}</code></pre>
</li>
</ol>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com2tag:blogger.com,1999:blog-5943570861711645804.post-86757758683044206122012-08-20T10:14:00.001+02:002012-08-20T15:12:44.180+02:00How to use mocks in controller tests<p>Even since I started to write tests for my Grails application I couldn't find many articles on using mocks. Everyone is talking about tests and TDD but if you search for it there isn't many articles.</p>
<p>Today I want to share with you a test with mocks for a simple and complete scenario. I have a simple application that can fetch Twitter tweets and present it to user. I use REST service and I use GET to fetch tweets by id like this: <a href="http://api.twitter.com/1/statuses/show/236024636775735296.json" target="_blank">http://api.twitter.com/1/statuses/show/236024636775735296.json</a>. You can copy and paste it into your browser to see a result.</p>
<p>My application uses Grails 2.1 with spock-0.6 for tests. I have <code>TwitterReaderService</code> that fetches tweets by id, then I parse a response into my <code>Tweet</code> class.</p>
<script src="https://gist.github.com/3370053.js?file=TwitterReaderService.groovy"></script>
<noscript>
<pre class="prettyprint">
class TwitterReaderService {
Tweet readTweet(String id) throws TwitterError {
try {
String jsonBody = callTwitter(id)
Tweet parsedTweet = parseBody(jsonBody)
return parsedTweet
} catch (Throwable t) {
throw new TwitterError(t)
}
}
private String callTwitter(String id) {
// TODO: implementation
}
private Tweet parseBody(String jsonBody) {
// TODO: implementation
}
}
class Tweet {
String id
String userId
String username
String text
Date createdAt
}
class TwitterError extends RuntimeException {}
</pre>
</noscript>
<p><code>TwitterController</code> plays main part here. Users call <code>show</code> action along with <code>id</code> of a tweet. This action is my subject under test. I've implemented some basic functionality. It's easier to focus on it while writing tests.</p>
<script src="https://gist.github.com/3370053.js?file=TwitterController0.groovy"></script>
<noscript>
<pre class="prettyprint">
class TwitterController {
def twitterReaderService
def index() {
}
def show() {
Tweet tweet = twitterReaderService.readTweet(params.id)
if (tweet == null) {
flash.message = 'Tweet not found'
redirect(action: 'index')
return
}
[tweet: tweet]
}
}
</pre>
</noscript>
<p>Let's start writing a test from scratch. Most important thing here is that I use mock for my <code>TwitterReaderService</code>. I do not construct <code>new TwitterReaderService()</code>, because in this test I test only <code>TwitterController</code>. I am not interested in injected service. I know how this service is supposed to work and I am not interested in internals. So before every test I inject a <code>twitterReaderServiceMock</code> into controller:</p>
<script src="https://gist.github.com/3370053.js?file=TwitterControllerSpec0.groovy"></script>
<noscript>
<pre class="prettyprint">
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(TwitterController)
class TwitterControllerSpec extends Specification {
TwitterReaderService twitterReaderServiceMock = Mock(TwitterReaderService)
def setup() {
controller.twitterReaderService = twitterReaderServiceMock
}
}
</pre>
</noscript>
<p>Now it's time to think what scenarios I need to test. This line from <code>TwitterReaderService</code> is the most important:</p>
<script src="https://gist.github.com/3370053.js?file=Signature.groovy"></script>
<noscript>
<pre class="prettyprint">
Tweet readTweet(String id) throws TwitterError
</pre>
</noscript>
<p>You must think of this method like a black box right now. You know nothing of internals from controller's point of view. You're only interested what can be returned for you:</p>
<ul>
<li>a <code>TwitterError</code> can be thrown</li>
<li><code>null</code> can be returned</li>
<li><code>Tweet</code> instance can be returned</li>
</ul>
<p>This list is your test blueprint. Now answer a simple question for each element: "What do I want my controller to do in this situation?" and you have plan test:</p>
<ul>
<li><code>show</code> action should redirect to index if <code>TwitterError</code> is thrown and inform about error</li>
<li><code>show</code> action should redirect to index and inform if tweet is not found</li>
<li><code>show</code> action should show found tweet</li>
</ul>
<p>That was easy and straightforward! And now is the best part: we use <code>twitterReaderServiceMock</code> to mock each of these three scenarios!</p>
<p>In Spock there is a good documentation about <a href="http://code.google.com/p/spock/wiki/Interactions" target="_blank"> interaction with mocks</a>. You declare what methods are called, how many times, what parameters are given and what should be returned. Remember a black box? Mock is your black box with detailed instruction, e.g.: <em>I expect you that if receive exactly one call to <code>readTweet</code> with parameter '1' then you should throw me a <code>TwitterError</code></em>. Rephrase this sentence out loud and look at this:</p>
<script src="https://gist.github.com/3370053.js?file=Spock0.groovy"></script>
<noscript>
<pre class="prettyprint">
1 * twitterReaderServiceMock.readTweet('1') >> { throw new TwitterError() }
</pre>
</noscript>
<p>This is a valid interaction definition on mock! It's that easy! Here is a complete test that fails for now:</p>
<script src="https://gist.github.com/3370053.js?file=TwitterControllerSpec1.groovy"></script>
<noscript>
<pre class="prettyprint">
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(TwitterController)
class TwitterControllerSpec extends Specification {
TwitterReaderService twitterReaderServiceMock = Mock(TwitterReaderService)
def setup() {
controller.twitterReaderService = twitterReaderServiceMock
}
def "show should redirect to index if TwitterError is thrown"() {
given:
controller.params.id = '1'
when:
controller.show()
then:
1 * twitterReaderServiceMock.readTweet('1') >> { throw new TwitterError() }
0 * _._
flash.message == 'There was an error on fetching your tweet'
response.redirectUrl == '/twitter/index'
}
}
</pre>
</noscript>
<script src="https://gist.github.com/3370053.js?file=result1.txt"></script>
<noscript>
<pre class="prettyprint">
| Failure: show should redirect to index if TwitterError is thrown(pl.refaktor.twitter.TwitterControllerSpec)
| pl.refaktor.twitter.TwitterError
at pl.refaktor.twitter.TwitterControllerSpec.show should redirect to index if TwitterError is thrown_closure1(TwitterControllerSpec.groovy:29)
</pre>
</noscript>
<p>You may notice <code>0 * _._</code> notation. It says: <em>I don't want any other mocks or any other methods called. Fail this test if something is called!</em> It's a good practice to ensure that there are no more interactions than you want.</p>
<p>Ok, now I need to implement controller logic to handle <code>TwitterError</code>.</p>
<script src="https://gist.github.com/3370053.js?file=TwitterController1.groovy"></script>
<noscript>
<pre class="prettyprint">
class TwitterController {
def twitterReaderService
def index() {
}
def show() {
Tweet tweet
try {
tweet = twitterReaderService.readTweet(params.id)
} catch (TwitterError e) {
log.error(e)
flash.message = 'There was an error on fetching your tweet'
redirect(action: 'index')
return
}
[tweet: tweet]
}
}
</pre>
</noscript>
<p>My tests passes! We have two scenarios left. Rule stays the same: <code>TwitterReaderService</code> returns something and we test against it. So this line is the heart of each test, change only returned values after <code>>></code>:</p>
<script src="https://gist.github.com/3370053.js?file=Spock0.groovy"></script>
<noscript>
<pre class="prettyprint">
1 * twitterReaderServiceMock.readTweet('1') >> { throw new TwitterError() }
</pre>
</noscript>
<p>Here is a complete test for three scenarios and controller that passes it.</p>
<script src="https://gist.github.com/3370053.js?file=TwitterControllerSpec.groovy"></script>
<noscript>
<pre class="prettyprint">
import grails.test.mixin.TestFor
import spock.lang.Specification
@TestFor(TwitterController)
class TwitterControllerSpec extends Specification {
TwitterReaderService twitterReaderServiceMock = Mock(TwitterReaderService)
def setup() {
controller.twitterReaderService = twitterReaderServiceMock
}
def "show should redirect to index if TwitterError is thrown"() {
given:
controller.params.id = '1'
when:
controller.show()
then:
1 * twitterReaderServiceMock.readTweet('1') >> { throw new TwitterError() }
0 * _._
flash.message == 'There was an error on fetching your tweet'
response.redirectUrl == '/twitter/index'
}
def "show should inform about not found tweet"() {
given:
controller.params.id = '1'
when:
controller.show()
then:
1 * twitterReaderServiceMock.readTweet('1') >> null
0 * _._
flash.message == 'Tweet not found'
response.redirectUrl == '/twitter/index'
}
def "show should show found tweet"() {
given:
controller.params.id = '1'
when:
controller.show()
then:
1 * twitterReaderServiceMock.readTweet('1') >> new Tweet()
0 * _._
flash.message == null
response.status == 200
}
}
</pre>
</noscript>
<script src="https://gist.github.com/3370053.js?file=TwitterController.groovy"></script>
<noscript>
<pre class="prettyprint">
class TwitterController {
def twitterReaderService
def index() {
}
def show() {
Tweet tweet
try {
tweet = twitterReaderService.readTweet(params.id)
} catch (TwitterError e) {
log.error(e)
flash.message = 'There was an error on fetching your tweet'
redirect(action: 'index')
return
}
if (tweet == null) {
flash.message = 'Tweet not found'
redirect(action: 'index')
return
}
[tweet: tweet]
}
}
</pre>
</noscript>
<p>The most important thing here is that we've tested controller-service interaction without logic implementation in service! That's why mock technique is so useful. It decouples your dependencies and let you focus on exactly one subject under test. Happy testing!</p>
Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com1tag:blogger.com,1999:blog-5943570861711645804.post-21081244516969646432012-08-06T09:52:00.000+02:002013-12-16T12:01:49.142+01:00Hibernate Envers with Grails 2.1.0<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLzNT2C9VYteyIELu_TZaUhJmL-bmYj6RxjFkhL9Wkadi4WoX15jI-zhhPUYjZ3V6RlKakeKTJXaLdvIlRAsBAdfCwhp8sB64437Vf12Ju59BgyBR7pACOWSr-9lh3SfAo6TIfNuFpi0A/s1600/hibernate.gif" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em"><img border="0" height="78" width="249" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLzNT2C9VYteyIELu_TZaUhJmL-bmYj6RxjFkhL9Wkadi4WoX15jI-zhhPUYjZ3V6RlKakeKTJXaLdvIlRAsBAdfCwhp8sB64437Vf12Ju59BgyBR7pACOWSr-9lh3SfAo6TIfNuFpi0A/s400/hibernate.gif" /></a></div>
<p>Our client requires that every entity in his Grails application has to be audited with detailed information: who and when did exactly what? It is a perfect opportunity to use <a href="http://docs.jboss.org/envers/docs/index.html">Hibernate Envers</a>! It turned out not as straightforward as I thought, so I want to share my experience with you.</p>
<h3>Introduction</h3>
<p>I use latest release of Grails with version 2.1.0. I've created a sample application on github for you as an example - <a href="https://github.com/SpOOnman/enversdemo" target="_blank">SpOOnman/enversdemo</a>. All files and techniques mentioned here can be found inside it. If you have other experiences with Grails and Envers working together, please share in comments.</p>
<h3>Grails Envers plugin</h3>
<p>First I've searched for a Grails plugin. I've found one outdated <a href="http://code.google.com/p/grails-envers-plugin/">on google code</a> and a (more modern) <a href="https://github.com/lucaslward/grails-envers-plugin">on github</a>. This plugin is created by Lucas Ward and it has great introductionary <a href="http://www.lucasward.net/2011/04/grails-envers-plugin.html">blog post</a> by author. This is a great place to start.</p>
<p>Unfortunately Lucas Ward's plugin supports Grails up 1.3.7 and it comes with outdated Envers version. I've searched through forks and I've found most up-to-date fork by Matija Folnovic: <a href="https://github.com/mfolnovic/grails-envers-plugin">https://github.com/mfolnovic/grails-envers-plugin</a>. It supports Grails 2.1 out of the box. Edit: Matija pointed out that credit should go to Jay Hogan and Damir Murat for their work on upgrading Envers plugin to Grails 2.</p>
<p><strong>Update (16.12.2013):</strong> As Glenn Filson pointed out in comments, envers plugin is now packaged in Grails central repository with a version 2.1.0. So packaging a plugin may be skipped, but remember to add plugin to <code>BuildConfig.groovy</code> wither way. Thanks for that Glenn!</p>
<p>Matija's plugin is not packaged nor published so you have to package it by yourself:</p>
<script src="https://gist.github.com/3175086.js?file=console 1"></script>
<p>Copy grails-envers-0.3-SNAPSHOT.zip (and rename to envers-0.3-SNAPSHOT.zip) to your application's lib diretory or publish to your company maven repository if you have one. Last step is to include a plugin in your BuildConfig.groovy:
<script src="https://gist.github.com/3175086.js?file=BuildConfig.groovy"></script>
<h3>Audit with Envers!</h3>
<p>It's really easy to audit all entities with Envers. All you have to do is to use <code>@Audit</code> annotation on entities. <a href="https://github.com/SpOOnman/enversdemo" target="_blank">SpOOnman/enversdemo</a> audits Hotels and Bookings:</p>
<script src="https://gist.github.com/3175086.js?file=Hotel.groovy,Booking.groovy"></script>
<p>Envers plugin comes with some handy methods. For example <code>Hotel.findAllRevisions()</code> returns list of previous revisions. Once again I recommend a great <a href="http://www.lucasward.net/2011/04/grails-envers-plugin.html" target="_blank">blog post</a> by Lucas Ward with many examples.
<h3>Grails and transactions</h3>
<p>Grails has some glitches working with Envers. Envers is closely tied to database transactions. This means that it runs its listeners at the transaction end, when session is flushed. This is not always the case in Grails and it's the cause of some problems. You need to make some small modifications to your application to be sure that Envers works fine.</p>
<ul>
<li>controllers - you need to annotate your controllers (or separate controller methods) with <code>@Transactional</code> and for every save you need to flush a session manually, e.g. <code>save(flush: true)</code>. Otherwise Envers may not be notified.</li>
<li>services in Grails are transactional by default. However you mey explicitily set them with <code>static transactional = true</code> to be sure that this is not altered. I recommend to use session flushing on every save as well.</li>
<li>BootStrap.groovy script is not transactional. If you want Envers to audit your changes in this script you need to wrap your inserts with transactions. You can achieve it by using <a href="http://grails.org/doc/latest/ref/Domain%20Classes/withTransaction.html" target="_blank">withTransaction</a> closure. You need session flushing too. Take a look at <a href="https://github.com/SpOOnman/enversdemo/blob/master/grails-app/conf/BootStrap.groovy" target="_blank">SpOOnman/enversdemo BootStrap.groovy</a> for an example.</li>
<li>integration tests wrap every test in a separate transaction that is rolled back at the end of a test, hence Envers won't work here. You need to disable wrapped transactions with <code>static transactional = false</code>. Remember that your changes are commited to database. To fulfill a contract of an empty database for every test you need to take care of cleaning up a database manually. <a href="https://github.com/SpOOnman/enversdemo/blob/master/test/integration/pl/refaktor/enversdemo/HotelIntegrationSpec.groovy" target="_blank">Here</a> is my sample integration test.</li>
</ul>
<h3>Add User to revision entities</h3>
<p>By default Envers comes with a DefaultRevisionEntity class and creates its instance for every change on audited instance. It keeps information about entity revision, date and modification type. It lacks information about a user that made a change. I want to extend it.</p>
<p>There is already a code inside a plugin (<a href="https://github.com/mfolnovic/grails-envers-plugin/blob/master/src/groovy/net/lucasward/grails/plugin/SpringSecurityRevisionListener.groovy" target="_blank">here</a> and <a href="https://github.com/mfolnovic/grails-envers-plugin/blob/master/src/groovy/net/lucasward/grails/plugin/SpringSecurityServiceHolder.groovy" target="_blank">here</a>) but it's not packaged with a plugin itself. I guess it's because it adds dependency to Spring Security. This not a problem for me since I already use <a href="code.google.com/p/spock/">Spring Security plugin</a> already in my application. I decided to add missing classes inside my application.</p>
<p>First I need a domain class - UserRevisionEntity. New instance of this class is created for every revision saved by Envers. It is a simple domain class with some extra annotations:
<script src="https://gist.github.com/3175086.js?file=UserRevisionEntity.groovy"></script>
<p>Notice that I've made currentUser field nullable. There may be some actions that doesn't require user to be logged in. Also, there is no user while executing BootStrap.groovy script.</p>
<p>Annotations <code>@RevisionNumber</code> and <code>@RevisionTimestamp</code> are required by Envers as described in <a href="http://docs.jboss.org/envers/docs/index.html#revisionlog" target="_blank">documentation</a>. <code>@RevisionEntity</code> annotation configures Envers to use non-default listener - SpringSecurityRevisionListener. It looks simple:</p>
<script src="https://gist.github.com/3175086.js?file=SpringSecurityRevisionListener.groovy"></script>
<p>SpringSecurityRevisionListener's newRevision method fills each UserRevisionEntity instances with currently logged User.</p>
<h3>Configuration</h3>
<p>Envers offers some configuration options listed on <a href="http://docs.jboss.org/envers/docs/index.html#configuration" target="_blank">documentation page</a>. Options can be set in persistence.xml. However in Grails there is no persistence.xml. You can add it (and Grails supports it), but I've found other way to configure properties. I use System.setProperties to configure Envers and I place it in grails-app/conf/spring/resources.groovy. This is an example to change Envers tables' prefix and suffix:</p>
<script src="https://gist.github.com/3175086.js?file=resources.groovy"></script>
<h3>Testing</h3>
<p>Testing Envers makes sense only with Grails integration tests. As I've mentioned earlier you must disable transactions that wrap your tests in order for Envers listeners to work. Also make sure you use withTransaction, session flushing and you've marked your controllers as <code>@Transactional</code>. There rules all stand in integration tests too. Example integration test can look like this:</p>
<script src="https://gist.github.com/3175086.js?file=HotelIntegrationSpec.groovy"></script>
<h3>Summary</h3>
<p>Hibernate Envers does a great job auditing my application. It is easy to use, despite all the small glitches I've mentioned here. Special thanks to plugin authors that package Envers library in a plugin that can be used out of the box. I really recommend it! It would be great to hear all your thoughts on Envers and Grails working together so I can improve this post for others too.</p>
<h3>Update 12.04.2013</h3>
<p>Lucas Ward has posted updaate entry on Grails Hibernate Envers plugin here: <a href="http://www.lucasward.net/2013/04/grails-envers-plugin-update.html">http://www.lucasward.net/2013/04/grails-envers-plugin-update.html</a>. Thanks!</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com26tag:blogger.com,1999:blog-5943570861711645804.post-31105861966157800452012-07-12T12:36:00.001+02:002013-01-11T09:43:47.184+01:00Private fields and methods are not private in groovy<p>I used to code in Java before I met groovy. Like most of you, groovy attracted me with many enhancements. This was to my surprise to discover that method visibility in groovy is handled different than Java!</p>
<p>Consider this example:</p>
<pre><code><span class="keyword">class</span> <span class="class">Person</span> {
<span class="keyword">private</span> <span class="class">String</span> <span class="field">name</span>
<span class="keyword">public</span> <span class="class">String</span> <span class="field">surname</span>
<span class="keyword">private</span> <span class="method">Person</span>() {}
<span class="keyword">private</span> <span class="class">String</span> <span class="method">signature</span>() { <span class="string">"</span>${<span class="field">name</span>?.<span class="method">substring</span>(<span class="number">0</span>, <span class="number">1</span>)}<span class="string">. </span>$<span class="field">surname</span><span class="string">"</span> }
<span class="keyword">public</span> <span class="class">String</span> <span class="method">toString</span>() { <span class="string">"I am </span>$<span class="field">name</span><span class="string"> </span>$<span class="field">surname</span><span class="string">"</span> }
}</code></pre>
<p>How is this class interpreted with Java?</p>
<ol>
<li>Person has private constructor that cannot be accessed</li>
<li>Field "name" is private and cannot be accessed</li>
<li>Method signature() is private and cannot be accessed</li>
</ol>
<p>Let's see how groovy interpretes Person:</p>
<pre><code><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="static">main</span>(<span class="class">String</span>[] <span class="parameter">args</span>) {
<span class="keyword">def</span> person = <span class="keyword">new</span> <span class="class">Person</span>() <span class="comment">// constructor is private - compilation error in Java</span>
<span class="method">println</span>(person.<span class="method">toString</span>())
person.@<span class="field">name</span> = <span class="string">'Mike'</span> <span class="comment">// access name field directly - compilation error in Java</span>
<span class="method">println</span>(person.<span class="method">toString</span>())
person.<span class="field">name</span> = <span class="string">'John'</span> <span class="comment">// there is a setter generated by groovy</span>
<span class="method">println</span>(person.<span class="method">toString</span>())
person.@<span class="field">surname</span> = <span class="string">'Foo'</span> <span class="comment">// access surname field directly</span>
<span class="method">println</span>(person.<span class="method">toString</span>())
person.<span class="field">surname</span> = <span class="string">'Bar'</span> <span class="comment">// access auto-generated setter</span>
<span class="method">println</span>(person.<span class="method">toString</span>())
<span class="method">println</span>(person.<span class="method">signature</span>()) <span class="comment">// call private method - compilation error in Java</span>
}</code></pre>
<p>I was really astonished by its output:</p>
<pre><code>I am null null
I am Mike null
I am John null
I am John Foo
I am John Bar
J. Bar</code></pre>
<p>As you can see, groovy does not follow visibility directives at all! It treats them as non-existing. Code compiles and executes fine. It's contrary to Java. In Java this code has several errors, pointed out in comments.</p>
<p>I've searched a bit on this topic and it seems that this behaviour is known since version 1.1 and there is a bug report on that: <a href="http://jira.codehaus.org/browse/GROOVY-1875">http://jira.codehaus.org/browse/GROOVY-1875</a>. It is not resolved even with groovy 2 release. As Tim Yates mentioned in <a href="http://stackoverflow.com/questions/7852370/private-method-groovy-is-not-private">this Stackoverflow question</a>: "<i>It's not clear if it is a bug or by design</i>". Groovy treats visibility keywords as a hint for a programmer.</p>
<p>I need to keep that lesson in mind next time I want to make some field or method private!</p>Tomasz Kalkosińskihttp://www.blogger.com/profile/12111381907111251016noreply@blogger.com2