tag:blogger.com,1999:blog-25064055127245464332024-02-20T17:28:02.203+01:00The groovy programmerhoubiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-2506405512724546433.post-79045803973558355182014-04-25T16:44:00.000+02:002014-04-29T09:15:50.348+02:00Customizing Twitter Bootstrap with the Lesscss Gradle plugin<div class="article">
<div id="content">
<div class="sect1">
<h2 id="_abstract">Abstract</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In this article I will show you how to customize the <a href="http://getbootstrap.com/">Twitter Bootstrap style sheets</a> and compile
them with the <a href="https://github.com/houbie/lesscss-gradle-plugin">Lesscss Gradle plugin</a>.</p>
</div>
<div class="paragraph">
<p>You won’t have to change the original sources. You won’t even have to download them manually.</p>
</div>
<div class="paragraph">
<p>I’ll also show how you can inspect the LESS sources in your browser (in stead of the generated CSS) and how to get productive
with automatic compilation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_quick_start">Quick start</h2>
<div class="sectionbody">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>If you already have gradle:</p>
<div class="paragraph">
<p>There’s only one file to download: <a href="https://raw.githubusercontent.com/houbie/less-bootstrap/master/build.gradle">build.gradle</a> :)<br>
Save it in the directory <em>less-bootstrap</em> and then:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="bash language-bash">cd less-bootstrap
gradle init
gradle lesscDaemon --info</code></pre>
</div>
</div>
</li>
<li>
<p>You don’t have Gradle yet:</p>
<div class="paragraph">
<p>Clone the github project with <code>git clone https://github.com/houbie/less-bootstrap</code>
or download and unpack the <a href="https://github.com/houbie/less-bootstrap/archive/master.zip">zip distribution</a>
and use the included gradle wrapper:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="bash language-bash">cd less-bootstrap
gradlew init
gradlew lesscDaemon --info</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Now you can:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>open <em>less-bootstrap/web/bootstrap-examples/theme/index.html</em> (or an other example)</p>
</li>
<li>
<p>change <em>less-bootstrap/web/less/custom-variables.less</em></p>
</li>
<li>
<p>reload the page to see the changes</p>
</li>
</ol>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
Before reloading the page in your browser, you’ll have to wait a few seconds until the style sheets are compiled.
If you don’t like waiting (who does?), see <a href="#_speeding_up_compilation">Speeding up compilation</a>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exploring_the_examples">Exploring the examples</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The examples are located in <em>less-bootstrap/web/bootstrap-examples</em>. When you open f.e. <em>less-bootstrap/web/bootstrap-examples/theme/index.html</em>
and inspect the <em>Learn more</em> button in Google Chrome, you will see something like this:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="https://lh3.googleusercontent.com/-TPZiYvvBzII/U1pfcMkgHWI/AAAAAAAAEek/TarFWuKQxlU/inspect.png" alt="Inspecting an element in Chrome">
</div>
<div class="title">Figure 1. Inspecting an element in Chrome</div>
</div>
<div class="paragraph">
<p>The inspector shows the LESS sources because the the <em>lessc</em> task is configured to generate source maps:</p>
</div>
<div class="listingblock">
<div class="title">Enabling source maps in <code>build.gradle</code></div>
<div class="content">
<pre class="CodeRay"><code class="java language-java">lessc {
...
<span class="comment">//generate source maps so that Google Chrome shows the less source in the inspector i.s.o. the raw CSS</span>
options.sourceMap = <span class="predefined-constant">true</span>
<span class="comment">//the generated css file contains a reference to the source map, this reference will be relative to</span>
<span class="comment">//the sourceMapBasepath in this case it will be in the same directory as the css itself</span>
<span class="comment">//(default location of source maps)</span>
options.sourceMapBasepath = file(<span class="string"><span class="delimiter">"</span><span class="content">$webDir/css</span><span class="delimiter">"</span></span>).absolutePath
<span class="comment">//we could try to specify the sourceMapxxx options so that the browser can load the LESS sources</span>
<span class="comment">//directly, but this is not trivial since our sources reside in different locations</span>
<span class="comment">//therefore we just copy all the less source code into the source map file</span>
options.sourceMapLessInline = <span class="predefined-constant">true</span>
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
At the moment of writing, Chrome is the only browser that supports source maps for CSS files.
<a href="http://robdodson.me/blog/2012/12/28/debug-less-with-chrome-developer-tools/">This blog</a> shows how to enable CSS source maps
if they are not enabled by default.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_customizing_the_style_sheet">Customizing the style sheet</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_where_is_the_code">Where is the code?</h3>
<div class="paragraph">
<p>We would like to change the background color of the <em>Learn more</em> button, but how do we locate its definition?</p>
</div>
<div class="paragraph">
<p>Again, by inspecting the element in Chrome, we see that the background color is defined in <em>buttons.less</em>.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="https://lh5.googleusercontent.com/-sXlXGMX19R8/U1pfbLga2cI/AAAAAAAAEeU/-KclOQC6MUM/background-color.png" alt="The button's background colour">
</div>
<div class="title">Figure 2. The button’s background colour</div>
</div>
<div class="paragraph">
<p>When we double-click <em>buttons.less</em>, the source is opened in the inspector:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="https://lh6.googleusercontent.com/-oVI92BKyc8k/U1pfboHJxDI/AAAAAAAAEeY/uYrmVS4tc1Y/buttons-less.png" alt="Buttons.less">
</div>
<div class="title">Figure 3. Buttons.less</div>
</div>
<div class="paragraph">
<p>We see that the variable that we need to change is <code>btn-primary-bg</code>. Unfortunately, we cannot navigate further anymore
in the inspector, so we have to search manually.</p>
</div>
<div class="paragraph">
<p>The bootstrap source files can be found in <em>less-bootstrap/build/bootstrap/web-app/less</em>. A text search leads us to <em>mixins.less</em>
for the <code>button-variant</code> definition and to <em>variables.less</em> for the background color variable:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="less language-less">@btn-primary-bg: @brand-primary;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Albeit not perfect, it is a lot easier to find the code in this way than if we would only see the raw CSS in the inspector.</p>
</div>
<div class="paragraph">
<p>At this point we have to decide whether we want to change only the color of the primary buttons, or if we want to change
the primary brand color.</p>
</div>
</div>
<div class="sect2">
<h3 id="_modifying_styles">Modifying styles</h3>
<div class="paragraph">
<p>There are 3 ways to modify the style sheets:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Overwrite variables in <em>build.gradle</em></p>
</li>
<li>
<p>Modify a copy of the original source</p>
</li>
<li>
<p>Create our own customization LESS file</p>
</li>
</ol>
</div>
<div class="sect3">
<h4 id="_overwriting_variables_in_em_build_gradle_em">Overwriting variables in <em>build.gradle</em></h4>
<div class="paragraph">
<p>The lesscss compiler allows us to declare new or overwrite existing variables via the commandline or in <em>build.gradle</em>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="java language-java">lessc {
...
options.modifyVars = [<span class="string"><span class="delimiter">'</span><span class="content">brand-primary</span><span class="delimiter">'</span></span>: <span class="string"><span class="delimiter">'</span><span class="content">purple</span><span class="delimiter">'</span></span>]
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Overwriting variables this way can be useful if you want f.e. to use a different color scheme for development builds than for release builds, but
it is not suitable for more involved customizations.</p>
</div>
</div>
<div class="sect3">
<h4 id="_modify_a_copy_of_the_original_source">Modify a copy of the original source</h4>
<div class="paragraph">
<p>The <em>lessc</em> task is configured to lookup LESS files first in <em>less-bootstrap/web/less</em>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="java language-java">lessc {
...
sourceDir <span class="string"><span class="delimiter">"</span><span class="content">$webDir/less</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">$buildDir/bootstrap/web-app/less</span><span class="delimiter">"</span></span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This means that if we would copy <em>variables.less</em> to <em>less-bootstrap/web/less</em> and modify it, it will take precedence over
the original file.</p>
</div>
<div class="paragraph">
<p>However, when we would like to upgrade to a newer bootstrap version, we would need to apply all our changes again in the
new file, which is far from ideal.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Changing <code>brand-primary</code> in our copy of <em>variables.less</em> won’t have any effect, it will always be overridden by
the value in <em>build.gradle</em>!
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_create_our_own_customization_less_file">Create our own customization LESS file</h4>
<div class="paragraph">
<p>The main LESS file, <em>bootstrap.less</em>, consists of only import statements. If we would append a few import statements to
include our own customization files, we wouldn’t have to change the original LESS code. This is exactly what the <em>init</em>
task does when it unpacks the bootstrap sources:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="java language-java"><span class="comment">//have our custom less files imported into bootstrap.less and theme.less</span>
file(<span class="string"><span class="delimiter">"</span><span class="content">$buildDir/bootstrap/web-app/less/bootstrap.less</span><span class="delimiter">"</span></span>).text += <span class="string"><span class="delimiter">'</span><span class="delimiter">'</span></span><span class="string"><span class="delimiter">'</span><span class="content">
@import "custom-variables.less";
@import "application.less";</span><span class="delimiter">'</span></span><span class="string"><span class="delimiter">'</span><span class="delimiter">'</span></span>
file(<span class="string"><span class="delimiter">"</span><span class="content">$buildDir/bootstrap/web-app/less/theme.less</span><span class="delimiter">"</span></span>).text += <span class="string"><span class="delimiter">'</span><span class="content">@import "custom-variables.less";</span><span class="delimiter">'</span></span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Now you only have to keep the customizations in your project’s source repository. Furthermore, switching to another version of
bootstrap becomes trivial.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_define_your_own_semantics">Define your own semantics</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As pointed out in this <a href="http://ruby.bvision.com/blog/please-stop-embedding-bootstrap-classes-in-your-html">blog</a>,
you should use html elements and/or CSS classes that outline the structure of your documents.</p>
</div>
<div class="paragraph">
<p><em>/less-bootstrap/web/less/application.less</em> defines a sample article structure that is used in
<em>less-bootstrap/web/bootstrap-examples/starter-template/semantics.html</em>.</p>
</div>
<div class="paragraph">
<p>Again, we are extending bootstrap without changing the original sources.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_speeding_up_compilation">Speeding up compilation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Although the <a href="https://github.com/houbie/lesscss">lesscss compiler</a> is the fastest Java LESS compiler, it is still very slow
compared with the original node.js compiler.</p>
</div>
<div class="paragraph">
<p>Fortunately, you can use the node.js <em>lessc</em> compiler in combination with the Lesscss Gradle Plugin:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay"><code class="java language-java">lesscDaemon {
engine = <span class="string"><span class="delimiter">'</span><span class="content">commandline</span><span class="delimiter">'</span></span>
lessExecutable = <span class="string"><span class="delimiter">'</span><span class="content">/opt/local/bin/lessc</span><span class="delimiter">'</span></span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, your style sheets will typically be compiled by the time you switched from the source editor to the browser.</p>
</div>
<div class="paragraph">
<p>The <code>lessExecutable</code> is only required when <em>lessc</em> is not on your path. In windows you should include the <em>.bat</em> or <em>.cmd</em> extension.</p>
</div>
<div class="paragraph">
<p>You can read <a href="http://lesscss.org/#using-less-installation">here</a> how to install the node.js <em>lessc</em> compiler.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
Use the fast node.js compiler in the <em>lesscDaemon</em> task to save time when developing the style sheets. Keep the default
(java rhino based) compiler in the <em>lessc</em> task to avoid installing node.js on your CI server and to have deterministic
builds that always use the same compiler version.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_resources">Resources</h2>
<div class="sectionbody">
<div class="hdlist">
<table>
<tr>
<td class="hdlist1">
Twitter Bootstrap
</td>
<td class="hdlist2">
<p><a href="http://getbootstrap.com/">http://getbootstrap.com/</a></p>
</td>
</tr>
<tr>
<td class="hdlist1">
LESS
</td>
<td class="hdlist2">
<p><a href="http://lesscss.org">http://lesscss.org</a></p>
</td>
</tr>
<tr>
<td class="hdlist1">
Lesscss
</td>
<td class="hdlist2">
<p><a href="https://github.com/houbie/lesscss">https://github.com/houbie/lesscss</a></p>
</td>
</tr>
<tr>
<td class="hdlist1">
Lesscss gradle plugin
</td>
<td class="hdlist2">
<p><a href="https://github.com/houbie/lesscss-gradle-plugin">https://github.com/houbie/lesscss-gradle-plugin</a></p>
</td>
</tr>
<tr>
<td class="hdlist1">
Gradle
</td>
<td class="hdlist2">
<p><a href="http://gradle.org">http://gradle.org</a></p>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>houbiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.com0tag:blogger.com,1999:blog-2506405512724546433.post-11194834993317227842014-03-28T22:32:00.001+01:002014-03-28T22:32:36.393+01:00Follow-up: JavaScript on the JVM, experimenting with Nashorn<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?lang=java"></script>
The release of JDK8 was a good opportunity to test again how fast the <a href="http://openjdk.java.net/projects/nashorn/">Nashorn JavaScript engine</a> is in compiling <a href="http://lesscss.org/">Less style sheets</a>.
<br />
I hoped that performance improved since <a href="http://houbie.blogspot.be/2013/06/javascript-on-jvm-experimenting-with.html">I last tried an early access</a> build, but alas...
<br />
<h1>
Setup</h1>
I recently released a new version of <a href="https://github.com/houbie/lesscss">lesscss</a> that supports 3 execution engines:
<br />
<ul>
<li><b><i>rhino 1.7R4</i>:</b> it runs a pre-compiled version of less.js in the highest optimization level (9)</li>
<li><b><i>nashorn</i>:</b> the JDK8 built-in version, which does not (yet) support pre-compilation nor optimization</li>
<li><b><i>node.js lessc</i>:</b> prepare a commandline string and execute it with <i>Runtime.exec</i></li>
</ul>
I compiled the Twitter Bootstrap style sheets using different engines.<br />
I used my mac book (2.66GHz core i7 with 8GB memory and JVM args -Xms512m -Xmx1500m -XX:MaxPermSize=320m).<br />
For each run I instantiated one engine for 15 consecutive compilations.<br />
<br />
As you can see, both rhino and nashorn perform better when the JVM warmed up, but the differences in performance are huge:<br />
<br />
<table style="height: 160px; width: 532px;">
<caption>Time needed to compile Twitter Bootstrap (seconds)<br />
The first row includes JavaScript compilation in case of Nashorn</caption>
<thead>
<tr>
<th style="text-align: center;">#</th>
<th style="text-align: center;">Rhino<br />
(optimized)</th>
<th style="text-align: center;">Nashorn</th>
<th style="text-align: center;">node.js</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">1</td>
<td style="text-align: center;">3.9</td>
<td style="text-align: center;">18.4</td>
<td style="text-align: center;">0.9</td>
</tr>
<tr>
<td style="text-align: center;">2</td>
<td style="text-align: center;">1.9</td>
<td style="text-align: center;">7.9</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">3</td>
<td style="text-align: center;">1.7</td>
<td style="text-align: center;">6.1</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">4</td>
<td style="text-align: center;">1.6</td>
<td style="text-align: center;">5.8</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">5</td>
<td style="text-align: center;">1.4</td>
<td style="text-align: center;">5.0</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">6</td>
<td style="text-align: center;">1.4</td>
<td style="text-align: center;">4.9</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">7</td>
<td style="text-align: center;">1.5</td>
<td style="text-align: center;">4.5</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">8</td>
<td style="text-align: center;">1.4</td>
<td style="text-align: center;">5.3</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">9</td>
<td style="text-align: center;">1.3</td>
<td style="text-align: center;">5.8</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">10</td>
<td style="text-align: center;">1.3</td>
<td style="text-align: center;">4.4</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">11</td>
<td style="text-align: center;">1.0</td>
<td style="text-align: center;">4.0</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">12</td>
<td style="text-align: center;">1.0</td>
<td style="text-align: center;">3.8</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">13</td>
<td style="text-align: center;">1.0</td>
<td style="text-align: center;">3.5</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">14</td>
<td style="text-align: center;">0.9</td>
<td style="text-align: center;">3.1</td>
<td style="text-align: center;">0.6</td>
</tr>
<tr>
<td style="text-align: center;">15</td>
<td style="text-align: center;">0.9</td>
<td style="text-align: center;">2.8</td>
<td style="text-align: center;">0.6</td>
</tr>
</tbody></table>
<h1>
Conclusions</h1>
Although this is not a real benchmark,
the figures differed less then 20% between runs and the trends are clear (at least for this use case):
<br />
<ul>
<li>Rhino with optimizations is still a lot faster then nashorn</li>
<li>While rhino got faster on JDK8, nashorn seems to got slower (see previous <a href="http://houbie.blogspot.be/2013/06/javascript-on-jvm-experimenting-with.html">blog</a>)</li>
<li>There is a big gap with node.js, despite the overhead of spawning a new process and writing its output to disk</li>
</ul>
houbiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.com0tag:blogger.com,1999:blog-2506405512724546433.post-88742357965625534902013-12-02T20:57:00.000+01:002013-12-02T21:10:11.988+01:00Open source releases: a piece of Gradle<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?lang=java"></script>
Yennick Trevels wrote a <a href="http://jedicoder.blogspot.be/2011/11/automated-gradle-project-deployment-to.html">great
blog</a> on how to set up a Gradle build to deploy to the Sonatype OSS Repository (and from there to maven central).
<br />
Here I will show how the Gradle release plugin can be configured to
<br />
<ul>
<li>streamline the release process</li>
<li>automatically provide download links to you latest release on Github</li>
</ul>
<h3>
The standard release process</h3>
The principles of the Gradle release plugin originate from the Maven release plugin. The release steps are:
<br />
<ul>
<li>check release preconditions (no uncommitted files and no snapshot dependencies)</li>
<li> get the release version number</li>
<li>build (and test) the release</li>
<li>tag the release</li>
<li>update the version number and commit it</li>
</ul>
<h3>
Configuration</h3>
Add the build dependency and apply the plugin:
<br />
<pre class="prettyprint lang-java">
buildscript {
dependencies {
classpath 'com.github.townsfolk:gradle-release:1.2'
...
}
...
}
apply plugin: 'release'
</pre>
The release plugin is not fully documented, but fortunately it is small and the code speaks for itself (its Gradle :)
<br />
In
<a href="https://github.com/townsfolk/gradle-release/blob/master/src/main/groovy/release/ReleasePluginConvention.groovy">ReleasePluginConvention.groovy</a>
you find all the properties that can be specified.
I changed the default versionPropertyFile (<i>gradle.properties</i>) to
<i>versions.txt</i>, to make it obvious to find the project version.
You can also see how to use complex version schemes.
<br />
<pre class="prettyprint lang-java">
release {
versionPropertyFile = 'version.txt'
//a map of [regular expression : increment closure],
//if the version matches one of the regexps, the corresponding
// closure is used to auto-increment the version
versionPatterns = [
// 1.2.3-groovy-1.8.4 -> next version: 1.2.4-groovy-1.8.4
/(\d+)-groovy-(.+$)/: {matcher, project ->
matcher.replaceAll("${(matcher[0][1] as int) + 1}-less-${matcher[0][2]}")
}
]
}
</pre>
The version needs to be read from the file:
<br />
<pre class="prettyprint lang-java">
//the release plugin expects the content to be 'version=xyz',
//without whitespace around the =
version = file('version.txt').text.split('=')[1].trim()
</pre>
<h3>
Build hooks</h3>
One of the most powerful features of Gradle is the ability to hook custom tasks about anywhere in the build cycle.
<br />
<i>gradle tasks --all</i> shows all the steps in the release task that we can hook into:<br />
<br />
<b>checkCommitNeeded</b> - Checks to see if there are any added, modified, removed, or un-versioned files.
<br />
<b>checkSnapshotDependencies</b> - Checks to see if your project has any SNAPSHOT dependencies.
<br />
<b>checkUpdateNeeded</b> - Checks to see if there are any incoming or outgoing changes that haven't been
applied locally.
<br />
<b>commitNewVersion</b> - Commits the version update to your SCM
<br />
<b>confirmReleaseVersion</b> - Prompts user for this release version. Allows for alpha or pre releases.
<br />
<b>createReleaseTag</b> - Creates a tag in SCM for the current (un-snapshotted) version. [uploadArchives]
<br />
<b>initScmPlugin</b> - Initializes the SCM plugin (based on hidden directories in your project's
directory)
<br />
<b>preTagCommit</b> - Commits any changes made by the Release plugin - eg. If the unSnapshotVersion tas
was executed
<br />
<b>release</b> - Verify project, release, and update version to next. [clean]
<br />
<b>unSnapshotVersion</b> - Removes "-SNAPSHOT" from your project's current version.
<br />
<b>updateVersion</b> - Prompts user for the next version. Does it's best to supply a smart default.<br />
<br />
Hooking in is straightforward:
<br />
<pre class="prettyprint lang-java">
//always clean before building a release
release.dependsOn clean
//upload to sonatype before tagging the VCS
createReleaseTag.dependsOn uploadArchives
</pre>
We should only upload release builds to the sonatype staging repository, so we tweak the 'uploadArchives' a little bit:
<br />
<pre class="prettyprint lang-java">
task uploadSnapshot(dependsOn: uploadArchives)
// the release task spawns a new GradleBuild that doesn't contain
// release itself, but it contains createReleaseTag
def sonatypeRelease = gradle.startParameter.taskNames.contains('createReleaseTag')
def sonatypeSnapshot = gradle.startParameter.taskNames.contains('uploadSnapshot')
if (sonatypeRelease) {
//only sign releases
signing {
sign configurations.archives
}
}
def sonatypeRepositoryUrl = sonatypeRelease ?
'https://oss.sonatype.org/service/local/staging/deploy/maven2/' :
'https://oss.sonatype.org/content/repositories/snapshots/'
uploadArchives {
repositories {
if (!(sonatypeRelease || sonatypeSnapshot)) {
mavenLocal()
} else {
mavenDeployer {
if (sonatypeRelease) {
beforeDeployment { deployment -> signing.signPom(deployment) }
}
repository(url: sonatypeRepositoryUrl) {
authentication(userName: sonatypeUsername,
password: sonatypePassword)
}
pom.project {
...
</pre>
<h3>
Provide download links</h3>
In the README.md we can include links to our artifacts on maven central:
<br />
<pre>
You can download coolapp from the [maven central repository]
(http://central.maven.org/maven2/org/awesome/coolapp/1.2.3-groovy-1.8.4/coolapp-1.2.3-groovy-1.8.4.zip)
</pre>
With a few extra lines of Groovy, we can make the links point to the new release. The modified README can be committed to Github together with the new snapshot version:
<br />
<pre class="prettyprint lang-java">
task updateReadme << {
File readme = file('README.md')
//the release version is the version before the release minus 'SNAPSHOT'
def releaseVersion = "${project['release.oldVersion']}".replaceAll('-SNAPSHOT', '')
//replace all occurrences of x.y.z-groovy-a.b.c with the new release version
readme.text = (readme.text =~ /\d\.\d(\.\d)?-groovy-\d\.\d(\.\d)?(-SNAPSHOT)?/)
.replaceAll("${releaseVersion}")
}
commitNewVersion.dependsOn updateReadme
</pre>
And that's all there is to it.
A working example can be found in the <a href="https://github.com/houbie/lesscss">lesscss project</a>.houbiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.com0tag:blogger.com,1999:blog-2506405512724546433.post-59309174506900922762013-10-22T22:10:00.000+02:002013-10-22T22:10:28.314+02:00Spock framework: writing tests at warp speed<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?lang=java"></script>
<a href="http://groovy.codehaus.org/">Groovy</a> is a superb language for automated tests: it is far more powerful than Java and it allows to skip lots of boilerplate code. The <a href="http://docs.spockframework.org/">Spock framework</a> adds a nice test specification DSL on top of that. In this post, you will find out more about my favorite Spock feature: <a href="http://docs.spockframework.org/en/latest/data_driven_testing.html">data driven testing</a>.<br />
<br />
<h3>
Write one test and get 40 for free</h3>
I build a <a href="https://github.com/houbie/lesscss">Java port</a> of the <a href="http://lesscss.org/">LESS CSS compiler</a>, originally written in JavaScript.<br />
The LESS compiler already has more than 40 test cases that compare a compiled LESS file with the expected CSS result. I only had to create one unit test that loops over all LESS files, compiles them and checks the result.<br />
<br />
<pre class="prettyprint lang-java">def "less compatibility tests"() {
expect:
compiler.compile(lessFile) == getCss(lessFile)
where:
lessFile << new File('test/less').listFiles().findAll { it.name.endsWith('.less') }
}
def getCss(File lessFile) {
return new File('test/css' + lessFile.getName().replace('.less', '.css')).text
}</pre>
<br />
Notice how you can tell Spock that it has to create one test for each variable in a collection:<br />
<br />
<pre class="prettyprint lang-java">where:
variable << collection</pre>
<br />
Also notice the absence of <i>assertEquals </i>in the expect block: we only need to write boolean conditions. As programmers (and even non-programmers), we are trained to recognize these comparisons, so they are easier to read, understand and maintain then the classical <i>assertXxx</i> method calls.<br />
<br />
<h3>
Test isolation</h3>
We could also write a plain JUnit test that loops over the files to test them, but the problem would then be test isolation: if one test fails, the test method is aborted and we won't know the status of the remaining tests.<br />
Spock, instead, runs an isolated test for each iteration. All failures are reported separately, but if all tests pass, you will see only one method in the test report.<br />
In the above example, it would be even better to have one test method with a descriptive name for each LESS file. This is what Spock's <i>Unroll</i> annotation does:<br />
<br />
<pre class="prettyprint lang-java">@Unroll
def "#lessFile.name compatibility test"() {...}</pre>
<br />
By using <i>#lessFile.name</i> in the method name, we get clear test reports:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-qpVzbp9ossM/UmbQCXJGY6I/AAAAAAAADNs/q_Tp4baKOyI/s1600/unroll.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="http://1.bp.blogspot.com/-qpVzbp9ossM/UmbQCXJGY6I/AAAAAAAADNs/q_Tp4baKOyI/s640/unroll.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<h3>
Data tables</h3>
Spock <i>where </i>blocks are not limited to one variable. If you want to populate more than one variable in each iteration, you can use the collection approach as shown above, or you can provide a table with values:<br />
<br />
<pre class="prettyprint lang-java">when:
def reader = new FileSystemResourceReader()
then:
reader.canRead(location) == canRead
where:
location | canRead
'file1.txt' | true
'../file2.txt' | true
'/no file' | false</pre>
<br />
This example will run 3 tests: one for each data row. <br />
Data tables are especially useful for testing the typical use cases and corner cases in one go.<br />
Syntactically, a data table is a bunch of unrelated <i>or </i>statements, so it may look strange at first sight. But if well formatted, data tables look like tables, and that's how Spock interprets them.<br />
Intellij IDEA users get an extra here: it knows about Spock data tables and can format them automatically.<br />
<br />
<h3>
Links</h3>
The full examples are part of the <a href="https://github.com/houbie/lesscss">Lesscss project at GitHub</a>. Feel free to post any comments or suggestions.houbiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.com0tag:blogger.com,1999:blog-2506405512724546433.post-73694205406473752032013-06-17T21:40:00.001+02:002013-06-17T21:40:55.144+02:00JavaScript on the JVM: experimenting with Nashorn<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js?lang=java"></script>
I recently experimented with the upcoming <a href="http://openjdk.java.net/projects/nashorn/">Nashorn JavaScript run-time</a> to compile <a href="http://lesscss.org/">Less style sheets</a>.
<br />
I hoped to boost the performance in comparison with existing Less compilers for the JVM, but the results where not what I expected...
<br />
<h1>
Motivation</h1>
Although I am a fan of <a href="http://twitter.github.io/bootstrap/index.html">Twitter Bootstrap</a> and Less CSS in general, I found that the Less compilation in Java projects could take several seconds and thus be really bad for development turnaround.
<br />
During Devoxx 2012, <a href="http://www.devoxx.com/display/DV12/Marcus+Lagergren" title="Marcus Lagergren">Marcus Lagergren</a> explained how much faster Nashorn was compared with <a href="https://developer.mozilla.org/en-US/docs/Rhino">Rhino</a> (being already included in the standard Java distribution). So I took it for a test drive.<br />
<h1>
Can't wait for Java 8</h1>
I didn't have JDK8 installed yet, so I forked a <a href="https://github.com/furosys">backport on GitHub</a> and build the nashorn.jar that provides a standard <i>javax.script.ScriptEngine</i> implementation.<br />
This made it easy to support both Rhino and Nashorn: by specifying <i>-Djava.ext.dirs=/path/to/nashorn, </i>Nashorn was used by default with a fallback to Rhino.<br />
<br />
<pre class="prettyprint lang-java">ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine scriptEngine = factory.getEngineByName("nashorn");
if (scriptEngine == null) {
scriptEngine = factory.getEngineByName("nashorn");
}
if (scriptEngine == null) {
throw new RuntimeException("No JavaScript script engine found");
}</pre>
<h1>
The compiler</h1>
I didn't use the Rhino specific less script, but instead used the standard <i>less-1.3.3.js. </i>I only had to add a few lines of JavaScript in front, to stub a little browser functionality, and add a compile function at the back to be called from Java.<br />
The Java code was rather simple:<br />
<pre class="prettyprint lang-java">scriptEngine.eval(getLessScriptReader());
String css =
((Invocable) scriptEngine).invokeFunction("compile", lessString);
</pre>
<h1>
The Bootstrap test</h1>
The Twitter Bootstrap style sheets compiled successfully with both Rhino and Nashorn<br />
Compilation with Rhino took 10 seconds on my Macbook, while Nashorn did in in 8 seconds. Not exactly impressive...<br />
To get an idea of the JavaScript compilation / execution ratio , I invoked the Less compile function multiple times, hereby reusing the JavaScript context.<br />
<br />
<table style="height: 160px; width: 532px;">
<caption>Time needed to compile Twitter Bootstrap (seconds)<br />
The first row includes JavaScript compilation</caption>
<thead>
<tr>
<th style="text-align: center;">#</th>
<th style="text-align: center;">Rhino</th>
<th style="text-align: center;">Rhino<br />
(optimized)</th>
<th style="text-align: center;">Nashorn<br />
JDK7</th>
<th style="text-align: center;">Nashorn<br />
JDK8</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">1</td>
<td style="text-align: center;">9.8</td>
<td style="text-align: center;">5.5</td>
<td style="text-align: center;">8.0</td>
<td style="text-align: center;">15.0</td>
</tr>
<tr>
<td style="text-align: center;">2</td>
<td style="text-align: center;">7.5</td>
<td style="text-align: center;">2.1</td>
<td style="text-align: center;">2.5</td>
<td style="text-align: center;">5.8</td>
</tr>
<tr>
<td style="text-align: center;">3</td>
<td style="text-align: center;">7.3</td>
<td style="text-align: center;">1.5</td>
<td style="text-align: center;">/</td>
<td style="text-align: center;">3.7</td>
</tr>
<tr>
<td style="text-align: center;">4</td>
<td style="text-align: center;">7.4</td>
<td style="text-align: center;">1.1</td>
<td style="text-align: center;">/</td>
<td style="text-align: center;">3.4</td>
</tr>
<tr>
<td style="text-align: center;">5</td>
<td style="text-align: center;">7.3</td>
<td style="text-align: center;">1.0</td>
<td style="text-align: center;">/</td>
<td style="text-align: center;">3.4</td>
</tr>
</tbody></table>
<br />
The first column is for Rhino invoked as described above using the <i>javax.script </i>interfaces. By default Rhino always runs in interpreted mode. Compare this with the second column, where the Rhino Context is used directly which allows to set the optimization level to 9 (highest level).<br />
The third column is for Nashorn on Java 7. The Nashorn backport apparently contains some bugs, causing the third Less compilation within the same JavaScript context to fail.<br />
The fourth column contains the results of the Less compilation using a JDK8 snapshot. The engine now works correctly, but the performance still needs to improve a lot.<br />
<h1>
Conclusions</h1>
I realize that the Nashorn project is still in alpha, but until the team comes up with an API that allows compiler optimizations like Rhino does, the latter still seems to be the best bet.<br />
<br />houbiehttp://www.blogger.com/profile/12820348159360663912noreply@blogger.com0