Category Archives: Groovy

[Links] Strings concatenation in Java and Groovy

Lately I had a discussion at work regarding strings concatenation in Java and Groovy. To clear the view I hit the web and found several interesting posts about it that I want to share but the truth is after reading this I know less than before 😉

http://www.javacodegeeks.com/2013/03/java-stringbuilder-myth-debunked.html
http://java-performance.info/primitive-types-to-string-conversion-and-string-concatenation/
http://stackoverflow.com/questions/11359333/string-concatenation-with-groovy

There is a little bit more – while searching the web I have found neat solution in latest Java with a class StringJoiner which allows programmer to forget about pluses or several <em>append()</em> calls.

OneToMany relations with ordering in Grails – one form solution

The article was written during development. Therefore final solution differs from the code presented in the beginning of this post. If You want to see how working code looks like just check my Github.

It is quite common situation – we want two domain classes to share one form. In addition there is also oneToMany relation between them. And to make things a little bit harder we need to keep order of many side of the relationship – despite delete or create operations. With simple drag&drop functionality. Of course in Grails. Are You ready? Let’s go.

I started with solution described by ObjectPartners, but it got one big problem. It was using additional jQuery plugin, and therefore was doing some kind of ‘under the hood’ job, which was not suitable for my needs. So I have switched to plain jQuery and its plugins mainly due to main information source about this topic. My solution is fairly similar to described in omarello post, but if You do not need other form elements that inputs in your list and do not even think about sorting and ordering them, solution provided by by ObjectPartners will suffice.

Grails way of oneToMany

Before coding there is an important issue raised in comments section. Imports required for code snippets to work include:
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.userdetails.UserDetails

We should start with two simple domain classes:

package com.wordpress.chlebik

class Article {

	String title
	ArticleType type
	boolean deleted

	static transients = [ 'deleted' ]

	static constraints = {
		title(size: 3..12, nullabe: false)
	}

	String toString() {
		title
	}

}

enum ArticleType {

	NEWS,
	STORY

}

package com.wordpress.chlebik

class Newspaper {

	String name
	List<Article> articles = []

	static hasMany = [articles: Article]

	static mapping = {
		articles cascade:"all-delete-orphan"
	  }

    static constraints = {
		name(nullable: false, blank: false, size: 3..16)
    }

	String toString() {
		name
	}
}

They are simple but provide several usefull features – like list of types in enum and constraints. They are important in this example, but for now we should just focus on simple relation. Newspaper consists of Articles – you should pay attention to the fact, that I have used not only belongsTo mapping, but directly declared that there is a List of Articles. Default Grails’ behaviour with oneToMany relations is to use Set. We want to maintain order fo our Articles so I used List.

If You run application with default data source settings – Grails will automatically create tables in memory (with h2 db engine). Just visit http://localhost:8080/YOURAPPNAME/dbconsole and see by yourself what is going on. We have two simple tables for domain classes and one join table – NEWSPAPER_ARTICLE. There are two columns with foreign keys and what is more important – there is articles_idx column, which is needed for keeping order of articles. And all that thanks to Grails’ db creation. Awesome.

We got model created, now it is time for web layer. Within Grails’ console issue a command:

generate-all com.wordpress.chlebik.Newspaper

and in a moment we have generated controller and views. Unfortunately they do not provide possibility to create new articles within newspaper but it gives us a solid code-base to proceed. First, we should create a newspaper with articles in it. I will not use form generated, as it lacks functionality we need. Nothing as simple as issuing this code on controller or bootstrap:

Newspaper n = new Newspaper(name: 'ChlebikZine')

Article a1 = new Article(title: 'Title1', type: ArticleType.NEWS)
Article a2 = new Article(title: 'Title2', type: ArticleType.NEWS)
Article a3 = new Article(title: 'Title3', type: ArticleType.STORY)
n.articles.add(a1)
n.articles.add(a2)
n.articles.add(a3)

n.save()

Edit and update existing domain class

After running the application we can visit http://localhost:8080/YOURAPPNAME/newspaper/show/1 to see how our newspaper is rendered (I’ve changed page source generated by Grails, eg. removed links to articles edition).

ChlebikZine

It is show action and it looks fine. To now we can switch to editing. I am interested in list with editable fields. Right now I also want to have delete link to remove existing records (we do not add new ones so far). So our _form.gsp should look like this.

<%@ page import="com.wordpress.chlebik.Newspaper" %>

<script type="text/javascript">

jQuery(document).ready( function() {

	$(document).on("click", ".deleteArticle",function(event) {	

		var tableBody = $('#articlesListTableBody');
		var rowToDelete = $(this).closest('tr');
		var rowId = rowToDelete.attr('rowId');		

		// This is for removing only already existing rows in DB.
		if( !$(rowToDelete).attr('newRow') ) {
			$(tableBody).append("<input type='hidden' name='articles[" + rowId + "].deleted' value='true' />");
		}

		$(rowToDelete).remove();
		return false;
	});

	$('.addNewArticle').click( function() {

	});

} );

</script>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'name', 'error')} required">
	<label for="name">
		<g:message code="newspaper.name.label" default="Name" />
		<span class="required-indicator">*</span>
	</label>
	<g:textField name="name" maxlength="16" required="" value="${newspaperInstance?.name}"/></div>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'articles', 'error')} ">
	<label for="articles">
		<g:message code="newspaper.articles.label" default="Articles" />

	</label>
<table id="articlesList">
<thead>
<tr>
<th>Title</th>
<th>Type</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="articlesListTableBody">
		<g:each in="${newspaperInstance.articles}" var="article" status="i">
<tr rowId="${i}">
<td>
					<g:textField required="" name="articles[$i].title" value="${article.title}"/>
					<g:hiddenField name="articles[$i].id" id="articles[$i].id" value="${article.id}"/></td>
<td>
					<g:select value="${article.type}" name="articles[${i}].type" from="${com.wordpress.chlebik.ArticleType?.values()}" keys="${com.wordpress.chlebik.ArticleType.values()*.name()}" /></td>
<td>
					<a href="#" class="deleteArticle">Delete article</a></td>
</tr>
</g:each></tbody>
</table>
</div>

It is quite simple. Now here is a catch.

In Grails versions before 2.2.x UPDATE method was working differently than shown below. Solution given by ObjectPartners is working then but in newer versions it is not! Check out StackOverflow question. My solution was tested in Grails 2.4.3 with Groovy 2.3.6 and is mainly based on the solution given by Omarello. But it is just partly true. Keep reading to see what I’ve changed to make it work.

Therefore update method of the controller should like this:

 @Transactional
    def update(Newspaper newspaperInstance) {
        if (newspaperInstance == null) {
            notFound()
            return
        }

        if (newspaperInstance.hasErrors()) {
            respond newspaperInstance.errors, view:'edit'
            return
        }

		newspaperInstance.articles.eachWithIndex{ v,i ->
			if( params['articles[' + i + '].deleted'] == 'true' ) {
				v.deleted = true
			}
		}

		newspaperInstance.articles.removeAll{ it.deleted }
        newspaperInstance.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'Newspaper.label', default: 'Newspaper'), newspaperInstance.id])
                redirect newspaperInstance
            }
            '*'{ respond newspaperInstance, [status: OK] }
        }
    }

If you know better solution please let me know – it seems that wiring between form data/params is not transffering deleted property into created Newspaper entity. I’ve tried using:

newspaper.properties = params

With params filled with proper-named attributes for articles but it is not working! So I had to use additional iteration over all articles to set their deleted property. Again – if there is something I am doing wrong please let me know.

Now we should think about adding new articles to our newspaper. As You have seen it is quite simple – we just need to add inputs/selects to our table (in a view layer) with proper name attribute and that is all. Grails should do all the hard work. So after table we add simple link:

<a href="#" class="addNewArticle">Add new article</a>

And of course do not forget about Javascript.

$('.addNewArticle').click( function() {
		var allArticles = $("#articlesListTableBody tr[rowId]");
		var rowId = 0;			

		// This operation is performed to allow safe-delete of newly created (not saved in DB) articles
		if( allArticles.length ) {
			var maxId = 0;
        	allArticles.each(function() {
            	maxId = Math.max(maxId, parseInt($(this).attr('rowId')));
        	});
        	rowId = maxId+1;
		} 			

		$("#articlesListTableBody").append( '<tr newRow="true" rowId="' + rowId  + '">' +
		'<td><input type="text" required="" name="articles[' + rowId + '].title" value=""/></td>' +
                 '<td><select name="articles[' + rowId + '].type" >' +
        	'<g:each in="${com.wordpress.chlebik.ArticleType?.values()}" var="type">
<option value="${type}">${type}</option></g:each>
</select></td>
' +
									'
<td><a href="#" class="deleteArticle">Delete article</a></td>
</tr>
');

		return false;
	});

Nothing new here. We just add another row in our table. Pay attention to the fact, that there is newRow attribute in newly created row. Now it is clear why there was check for that attribute in delete function – if new article was not stored in DB, removal of it is not needed to be presented with deleted property set. You can play around with above solution – adding and deleting articles was never so easy. There is one thing to add – I resigned from cloning existing rows like it was presented in Omorello post. It is possbile when there are for sure rows in articles list and in my way – we can start with empty list so there is nothing to clone. Appending pure strings is maybe more low-level, but gives developer total control (which was compromised by using writetable-plugin).

Validate me

So far we did not checked two things – creation of totally new newspaper (that will come in a moment), ad validation (in facts it is about re-rendering of the view). Let’s have a look.

In generated views there is required attribute in inputs which are responsible for rendering domain class properties that have nullable : false in constraints. Newspaper name is one of them. Let’s see what will happen if we remove that attribute in GSP and submit empty newspaper name.

SaveSuccess

Apparently everything is all-right. Added article was successfully persisted in the DB. That is because our newspaper is separated from articles – constraint violation on newspaper do not stop persisting new article (because it is proper entity). Now let’s try to remove required attribute from article title and try to submit new article without it – sorry. We receive error message.

NPE

Do not ask me why and what does it mean. fortunately I know what helps – removing @Transactional annotation on our update method in controller!. If you remove it, form will re-render with proper error message. But try to submit form another time with new article empty title. It will give us error with finding deleted property in our code.

newspaperInstance.articles.removeAll{ it.deleted }

Somehow Grails managed to create new article which violates constraint (empty title) and is trying to save it! The cure for this is adding if statement in GSP that is listing all articles.

<g:each in="${newspaperInstance.articles}" var="article" status="i">
<tr rowId="${i}">
<td>
					<g:textField required="" name="articles[$i].title" value="${article.title}"/>
					<g:if test="${article.id}">
						<g:hiddenField name="articles[$i].id" id="articles[$i].id" value="${article.id}"/>
					</g:if></td>
<td>
					<g:select value="${article.type}" name="articles[${i}].type" from="${com.wordpress.chlebik.ArticleType?.values()}" keys="${com.wordpress.chlebik.ArticleType.values()*.name()}" /></td>
<td>
					<a href="#" class="deleteArticle">Delete article</a></td>
</tr>
</g:each>

This is the second time I do not know why Grails behaves like this – I understand that when there is no id attribute Grails will treat created domain class as new instance to persist. But how can it try to persist an entity which fails validation! Just to remember, generated update method has at the beginning:

if (newspaperInstance == null) {
      notFound()
      return
}

if (newspaperInstance.hasErrors()) {
     respond newspaperInstance.errors, view:'edit'
     return
}

Why this works for the first empty-title submit and fails at the second – I have no idea. Fortunately adding show-id logic in GSP helped.

But I want new newspaper

We started this topic from existing entity and editing it. It was easier that way to create clean code and show what is essential in oneToMany in one form. Right now we are going to create new newspaper and add some articles to it. There is already generated form and controller action. The truth is that – it works 😉 But only if we do not start to fool around validation again. To make long things short – there is a problem with treating newly added articles as new ones, not stored in DB (therefore they do not have id). _form.gsp must be modified in a section reponsobile for rendering article list (mainly safe-operator logic).

<table id="articlesList">
<thead>
<tr>
<th>Title</th>
<th>Type</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="articlesListTableBody">
		<g:each in="${newspaperInstance.articles}" var="article" status="i">
<tr <g:if test="${!article?.id}">newRow="true"</g:if> rowId="${i}">
<td>
					<g:textField required="" name="articles[$i].title" value="${article?.title}"/>
					<g:if test="${article?.id}">
						<g:hiddenField name="articles[$i].id" id="articles[$i].id" value="${article?.id}"/>
					</g:if></td>
<td>
					<g:select value="${article?.type}" name="articles[${i}].type" from="${com.wordpress.chlebik.ArticleType?.values()}" keys="${com.wordpress.chlebik.ArticleType.values()*.name()}" /></td>
<td>
					<a href="#" class="deleteArticle">Delete article</a></td>
</tr>
</g:each></tbody>
</table>

Now we can do whatever we want with creation of new entity – try to break validation, add and delete articles, try to break articles’ validation, whatever You want. It just works 😉

Gimme more – I want to sort things out

Generally I did not expect sorting to work so easily and quickly. Of course You need to download/link jQeury UI with sortable. After that You must change _form.gsp to this:

<%@ page import="com.wordpress.chlebik.Newspaper" %>

<script type="text/javascript">

jQuery(document).ready( function() {

	$(document).on("click", ".deleteArticle",function(event) {	

		var tableBody = $('#articlesListTableBody');
		var rowToDelete = $(this).closest('tr');	

		// This is for removing only already existing rows in DB.
		if( !$(rowToDelete).attr('newRow') ) {
			var rowId = $(rowToDelete).attr('rowId')
			var articleId = $("input[name='articles[" + rowId + "].id']").val();
			$(tableBody).append("<input type='hidden' name='articles[" + articleId + "].deleted' value='true' />");
		}

		$(rowToDelete).remove();
		return false;
	});

	$('.addNewArticle').click( function() {
		var allArticles = $("#articlesListTableBody tr[rowId]");
		var rowId = 0;			

		// This operation is performed to allow safe-delete of newly created (not saved in DB) articles
		if( allArticles.length ) {
			var maxId = 0;
        	allArticles.each(function() {
            	maxId = Math.max(maxId, parseInt($(this).attr('rowId')));
        	});
        	rowId = maxId+1;
		} 			

		$("#articlesListTableBody").append( '<tr newRow="true" rowId="' + rowId  + '">' +
		'<td><input required="true" type="text"  name="articles[' + rowId + '].title" value=""/></td>' +
                '<td><select name="articles[' + rowId + '].type" >' +
		'<g:each in="${com.wordpress.chlebik.ArticleType?.values()}" var="type">
                  <option value="${type}">${type}</option>
                 </g:each></select></td>' +
                 '<td  class="moveRow"><a href="#" class="deleteArticle">Delete article</a></td>
                  <td class="moveRow">Move</td></tr>');

		return false;
	});

	 $('#articlesListTableBody').sortable({
	        stop: function (event, ui) {
	            updateNames($(this))
	        },
	        handle: '.moveRow',
	    });

	 function updateNames($tbody) {
		    $tbody.find('tr').each(function (idx) {
		        var $inp = $(this).find('input,select,textarea');
		        $(this).attr('rowId', idx);
		        $inp.each(function () {
		            this.name = this.name.replace(/(\[\d\])/, '[' + idx + ']');
		        })
		    });
	}

   } );

</script>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'name', 'error')} required">
	<label for="name">
		<g:message code="newspaper.name.label" default="Name" />
		<span class="required-indicator">*</span>
	</label>
	<g:textField name="name" required="" maxlength="16"  value="${newspaperInstance?.name}"/></div>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'articles', 'error')} ">
	<label for="articles">
		<g:message code="newspaper.articles.label" default="Articles" />

	</label>
<table id="articlesList">
<thead>
<tr>
<th>Title</th>
<th>Type</th>
<th>Delete</th>
<th>Move</th>
</tr>
</thead>
<tbody id="articlesListTableBody">
		<g:each in="${newspaperInstance.articles}" var="article" status="i">
<tr <g:if test="${!article?.id}">newRow="true"</g:if> rowId="${i}">
<td>
					<g:textField required="" name="articles[$i].title" value="${article?.title}"/>
					<g:if test="${article?.id}">
						<g:hiddenField id="" name="articles[$i].id" value="${article?.id}"/>
					</g:if></td>
<td>
					<g:select value="${article?.type}" name="articles[${i}].type" from="${com.wordpress.chlebik.ArticleType?.values()}" keys="${com.wordpress.chlebik.ArticleType.values()*.name()}" /></td>
<td>
					<a href="#" class="deleteArticle">Delete article</a></td>
<td class="moveRow">
					Move</td>
</tr>
</g:each></tbody>
</table>
<a href="#" class="addNewArticle">Add new article</a></div>

JavaScript code used in this example comes from StackOverflow question – it works just out-of-the-box. But there is a catch – only with already persisted entities. So create new newspaper, add several new articles, save them. After that edit newspaper switch order and save it again. It works like a charm.

The problems begin when removal of rows or changing order of not yet persisted rows – I receieved many different errors and logical errors. It took me about two hours – after that I was not sure what was the reason that it started working 😉 But it does – I definetly added refreshing input-indexes after row removal in Javascript (same action that is triggered when sorting ends). I’ve removed delete property completly – and it still works. Magic.

So here is view and controller.

<%@ page import="com.wordpress.chlebik.Newspaper" %>

<script type="text/javascript">

jQuery(document).ready( function() {

	$('#articlesListTableBody').sortable({
        stop: function (event, ui) {
            updateNames($(this))
        },
        handle: '.moveRow',
    });

 	function updateNames($tbody) {
	    $tbody.find('tr').each(function (idx) {
	        var $inp = $(this).find('input,select,textarea');
	        $(this).attr('rowId', idx);
	        $inp.each(function () {
	            this.name = this.name.replace(/(\[\d\])/, '[' + idx + ']');
	        })
	    });
	}

	$(document).on("click", ".deleteArticle",function(event) {	

		var tableBody = $('#articlesListTableBody');
		var rowToDelete = $(this).closest('tr');	

		$(rowToDelete).remove();
		updateNames(tableBody);
		return false;
	});

	$('.addNewArticle').click( function() {
		var allArticles = $("#articlesListTableBody tr[rowId]");
		var rowId = 0;			

		// This operation is performed to allow safe-delete of newly created (not saved in DB) articles
		if( allArticles.length ) {
		    var maxId = 0;
        	    allArticles.each(function() {
            	        maxId = Math.max(maxId, parseInt($(this).attr('rowId')));
        	    });
        	    rowId = maxId+1;
		} 			

		$("#articlesListTableBody").append( '<tr newRow="true" rowId="' + rowId  + '">' + 									
                 '<td><input required="true" type="text"  name="articles[' + rowId + '].title" value=""/></td>' +
                 '<td><select name="articles[' + rowId + '].type" >' +
		'<g:each in="${com.wordpress.chlebik.ArticleType?.values()}" var="type">
                 <option value="${type}">${type}</option></g:each></select></td>' +
		'<td  class="moveRow"><a href="#" class="deleteArticle">Delete article</a></td><td class="moveRow">Move</td></tr>');

		return false;
	});

} );

</script>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'name', 'error')} required">
	<label for="name">
		<g:message code="newspaper.name.label" default="Name" />
		<span class="required-indicator">*</span>
	</label>
	<g:textField name="name" required="" maxlength="16"  value="${newspaperInstance?.name}"/></div>
<div class="fieldcontain ${hasErrors(bean: newspaperInstance, field: 'articles', 'error')} ">
	<label for="articles">
		<g:message code="newspaper.articles.label" default="Articles" />

	</label>
<table id="articlesList">
<thead>
<tr>
<th>Title</th>
<th>Type</th>
<th>Delete</th>
<th>Move</th>
</tr>
</thead>
<tbody id="articlesListTableBody">
		<g:each in="${newspaperInstance.articles}" var="article" status="i">
<tr <g:if test="${!article?.id}">newRow="true"</g:if> rowId="${i}">
<td>
	<g:textField id="" required="" name="articles[$i].title" value="${article?.title}"/>
		<g:if test="${article?.id}">
			<g:hiddenField id="" name="articles[$i].id" value="${article?.id}"/>
		</g:if></td>
<td>
	<g:select value="${article?.type}" name="articles[${i}].type" from="${com.wordpress.chlebik.ArticleType?.values()}" keys="${com.wordpress.chlebik.ArticleType.values()*.name()}" /></td>
<td>
	<a href="#" class="deleteArticle">Delete article</a>
</td>
<td class="moveRow">Move</td>
</tr>
</g:each></tbody>
</table>
<a href="#" class="addNewArticle">Add new article</a></div>
 def update(Newspaper newspaperInstance) {

        if (newspaperInstance == null) {
            notFound()
            return
        }

        if (newspaperInstance.hasErrors()) {
            respond newspaperInstance.errors, view:'edit'
            return
        }

	newspaperInstance.articles.clear()
	newspaperInstance.properties = params

	newspaperInstance.save flush:true

        request.withFormat {
            form multipartForm {
                flash.message = message(code: 'default.updated.message', args: [message(code: 'Newspaper.label', default: 'Newspaper'), newspaperInstance.id])
                redirect newspaperInstance
            }
            '*'{ respond newspaperInstance, [status: OK] }
        }
    }

Almost finished

Looking back at all the trouble I had with figuring out the proper solution made me wonder – why do not use AJAX? This is fine idea but I wanted to deal with pure Grails’ form handling. Full source (with final solution) can be found on my Github. As I mentioned before – I have used Grails 2.4.3 with Groovy 2.3.6.

ENUM in Grails with i18n support

Enums are pretty usefull Java feature. However, developers often encounter problems with two things – reflecting enum in database and i18n. Database is often a easy thing – store enum value in character column or even in specialised column type (eg. in MySQL). Internationalization is a little bit harder but fortunately Grails makes it so easy. The goal of this tutorial is to show how Grails can present enum values in a view layer with translated values.

The key interface is MessageSourceResolvable  which comes of course from Spring. We can have simple enum like this:

 

enum WarriorLevel implements org.springframework.context.MessageSourceResolvable {

    BEGGINER, NOVICE, APPRENTICE, MASTER

    // Methods inherited from interface
    public Object[] getArguments() { [] as Object[] }
    public String[] getCodes() { [ name() ] }
    public String getDefaultMessage() { name() }
}

Nothing new except implementation of methods inherited from interface. They are very simple, just for demonstration purposes.
Another thing to be done are internationalization entries. Grails keeps them in i18n folder with separate files for every language that can be supported. I come from Poland therefore my filename is messages_pl.properties. For given enum entries look like that (prefix is just for clearance):

com.wordpress.chlebik.BEGGINER=nowy
com.wordpress.chlebik=nowicjusz
com.wordpress.chlebik=adept
com.wordpress.chlebik=mistrz

Now the only thing is to put everything in motion – in a view layer we naturally use Grails tags to create select element:

<g:select name="chlebikTest" from="${WarriorLevel?.values()}" keys="${WarriorLevel .values()*.name()}" value="${warrior?.level?.name()}" valueMessagePrefix="com.wordpress.chlebik" />

And that’s all folks. Here are some links about it:

Grails page (check out last entry)
Enum in Grails domain from StackOverflow
Enum in GSP view from StackOverflow

Incrementing Grails application version during WAR packaging

Grails comes with several predefined properties, which can be used in application or build process. One of them is application version. It can be found in application.properties file and the usual way is to change it manually. Of course we can find a plugin – version updater – that makes that via Grails console. But what about situation in which every WAR creation should trigger version update?

Quick fix for that can be seen below (it is based on the script I have found on this blog). It is a simple script which should be places in /scripts folder of our project in a file named _Events.groovy. During WAR creation this script will be read and executed. Of course logic presented is fairly simple and lacks some parameters validation but I will leave it up to the developer.


eventCreateWarStart = { warName, stagingDir ->
	
	Map<String,Integer> mappings = [ 'M' : 0, 'm' : 1, 'p' : 2 ]
	String versionParam = System.getProperty('version.update.position', 'M')
	def lastAppVersionNumberList = metadata.'app.version'.split('\\.')
			   
	
	println "*** Started customised version update of Grails app. Current version: ${metadata.'app.version'}"
				
	lastAppVersionNumberList[ mappings[versionParam] ] =        Integer.valueOf(lastAppVersionNumberList[mappings[versionParam]]) + 1
	
	metadata.'app.version' = lastAppVersionNumberList.join('.')
	metadata.persist() 
	
	println "*** Ended customised version update of Grails app. Current version: ${lastAppVersionNumberList.join('.')}"
}

LDAP Authentication and DB authorisation with Grails Spring Security

Recently I faced quite simple problem – allow application to authenticate users via LDAP but authorise them via database. It is a common solution – we make sure that only company’s users are logging into app, but there comes flexibility with ACL stored locally. In Grails it looked pretty simple until I started to integrate this solution into my application. It took me a while to put everything together so I decided to share it.

To make long things short – there is an offical documentation but IMHO, it should be tweaked a little to be more user-friendly. The most important thing to understand are sides and roles that take place in logging process. There is LDAP instance, where we send requests to authorise user. LDAP response must be transmitted to our app and full our users’ object. Meanwhile there is also roles read from database. In addition there is simple check – if logging user has no account in our app, we will create it with default roles.

My app uses simple domain classes provided by Spring Security (User, Role and UserRole). If You are not familiar with them I suggest reading official docs. First we create UserMappingDetails class, which is simple POJO that will store user data (login, password, account data) and authorities (roles that user has).

class ChlebikUserDetails extends GrailsUser {

   ChlebikUserDetails(String username, String password, boolean enabled,
                 boolean accountNonExpired, boolean credentialsNonExpired,
                 boolean accountNonLocked,
                 Collection<GrantedAuthority> authorities,
                 long id, String fullName) {
      super(username, password, enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, authorities, id)      
   }
}

Next we create mapping class, which will translate LDAP response to our application user.

class ChlebikUserDetailsContextMapper implements UserDetailsContextMapper {

	private static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
		
	@Override
	@Transactional
	public ChlebikUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<SimpleGrantedAuthority> authority) {
		
		User user = User.findByUsername(username)
		
		if(!user) {					
				// Create new user and save to the database                                
				user = new User()
				user.username = username				
				user.password = "123" // doesn't matter
				user.save(flush: true, failOnError: true)
									
				UserRole userRole = new UserRole()
				userRole.user = user
				userRole.role = Role.findByAuthority('USER') // Default role in my app
				userRole.save(flush: true, failOnError: true)			
		}
						 
		def authorities = user.getAuthorities().collect { new SimpleGrantedAuthority(it.authority) }		
		def userDetails = new ChlebikUserDetails(username, user.password, user.enabled, false,
					false, false, authorities, user.id, username)
		return userDetails
	}

	
	@Override
	public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {}	
}

Ok, we are getting closer. Last class to create is service that will be called by Spring Security to retrieve our user when needed. It cannot be put in Grails’ service directory!!! Just place it in src/groovy

class PrePopulateUserDetailsService implements GrailsUserDetailsService  {
	
	Logger logger = Logger.getLogger(getClass())
	LdapUserDetailsService ldapUserDetailsService
	
	static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
		return loadUserByUsername(username, true)
	}
	
	@Override
	@Transactional	// Services in Grails are transactional by default but it is normal class so we put this annotation
	public UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException, DataAccessException {
				
		User user = User.findByUsername(username)
		def authorities = user.getAuthorities().collect {new SimpleGrantedAuthority(it.authority)}
		
		return new ChlebikUserDetails(user.username, user.password, user.enabled,
			!user.accountExpired, !user.passwordExpired,
			!user.accountLocked, authorities ?: NO_ROLES, user.id,
			user.username)   
	}
}

That’s all. Of course we need to add some config to our application. First we visit configuration folder and spring subfolder. There in resources.groovy we put this (registering beans):

beans = {		
	ldapUserDetailsMapper(com.wordpress.chlebik.ChlebikUserDetailsContextMapper)
	userDetailsService(com.wordpress.chlebik.PrePopulateUserDetailsService)
}

And in out Config.groovy (or whatever user-defined config file You are using) we should have several config properties. I am putting them all (to allow Grails connect to LDAP).

grails.plugin.springsecurity.providerNames = ['rememberMeAuthenticationProvider', 'ldapAuthProvider', 'anonymousAuthenticationProvider']

// Probably better to keep this data in an external file for security reasons
grails.plugin.springsecurity.ldap.context.managerDn = ''
grails.plugin.springsecurity.ldap.context.managerPassword = ''
grails.plugin.springsecurity.ldap.context.server = ''

grails.plugin.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory
grails.plugin.springsecurity.ldap.search.base = 'CN=putwhatyoumust,O=putwhatyoumust'
grails.plugin.springsecurity.ldap.authenticator.dnPatterns=='uid={0},CN=putwhatyoumust,O=putwhatyoumust'
grails.plugin.springsecurity.ldap.search.filter="uid={0}" 
grails.plugin.springsecurity.ldap.search.searchSubtree = true
grails.plugin.springsecurity.ldap.auth.hideUserNotFoundExceptions = false

// These are crucial for LDAP/DB configuration
grails.plugin.springsecurity.ldap.mapper.userDetailsClass='com.wordpress.chlebik.ChlebikUserDetails'
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = false
grails.plugin.springsecurity.ldap.authorities.retrieveDatabaseRoles = true

And it magically works. Above code is the result of several hours on the web. Below I put all links that helped me a lot.

Grails passwords salted
Juan Vazquez GitHub
Most helpfull Nabble
Customizing authentication in your grails app
Official plugin page

Groovy 2.3.5 backward compatibility with Spock unit tests

In my new workplace there is a problem – corporate firewall, which is a common problem in IT world. Therefore update sites of Eclipse are blocked, which means quite a mess with dependencies and plugin management.

My main concern was Spock, which I have run using built-in Groovy in version 2.3.6, while tests and whole application was written in Grails 2.2.3 with Groovy a little bit older 😉 Finally it came to my attention that hated exception

Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.runtime.typehandling.ShortTypeHandling at java.net.URLClassLoader$1.run(URLClassLoader.java:372)

can be easily fixed in a way that Guillaume Laforge wrote. Just downloaded JAR, added to project’s classpath and there it is – my Spock test are working like charm.