Friday, October 21, 2011

Grails dynamic finders not working in Unit Tests

I ran into a problem with my unit test in Grails.

One of the dynamic finders was not working. What was strange was that it worked fine when I ran the app normally. It only failed in the unitTests.


groovy.lang.MissingMethodException: No signature of method: static com.domain.myDomain.findByCode() is applicable for argument types: (java.lang.String) values: [myCode]
at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1357)
at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1343)
at groovy.lang.ExpandoMetaClass.invokeStaticMethod(ExpandoMetaClass.java:1082)
at

Solution.

When unit testing, grails mocks out all backend access. In order to do this it must dynamically update the domain classes (e.g. save method), so that they dont try to talk to the DB.

Therefore when using any unit testing on domain object you must first mock it out. This is easily done in the unitTest class in the setUp() method

e.g.
mockDomain myDomain


It can save you a lot of hassle

Tuesday, October 18, 2011

Stack trace cleanup

Groovy has a handy class for sanitize stack traces. (i.e. it removes any java, groovy classes from the classpath, so that just so called 'Business' classes remain.

Of course if you are using thirdparty libraries then this might not cleanse the stack trace enough. Therefore it might be useful to append extra ignorable packages into the ignore list.

e.g.

// Add any extra package names here
String[] GROOVY_PACKAGES =
System.getProperty("groovy.sanitized.stacktraces",
"groovy.," +
"org.codehaus.groovy.," +
"java.," +
"javax.," +
"sun.," +
"gjdk.groovy.,"
).split("(\\s|,)+");


public static Throwable sanitize(Throwable t) {
// Note that this getBoolean access may well be synced...
if (!Boolean.getBoolean("groovy.full.stacktrace")) {
StackTraceElement[] trace = t.getStackTrace();
List newTrace = new ArrayList();
for (StackTraceElement stackTraceElement : trace) {
if (isApplicationClass(stackTraceElement.getClassName())) {
newTrace.add(stackTraceElement);
}
}
// We don't want to lose anything, so log it
STACK_LOG.log(Level.WARNING, "Sanitizing stacktrace:", t);


StackTraceElement[] clean = new StackTraceElement[newTrace.size()];
newTrace.toArray(clean);
t.setStackTrace(clean);
}
return t;
}

Thursday, October 13, 2011

Grails local plugin repository

If you are creating your own grails plugins, then you need to
1/ Store them on a central server
2/ Inform grails to check this server to find your plugins before going online to download them

There are 2 ways to do this (see http://grails.org/doc/1.3.x/guide/12.%20Plug-ins.html)

1/ Grails Compatible Repositories
This is easily achieved by creating (or updating if it already exists) the $HOME/.grails/settings.groovy file

e.g. to add myPluginRepository

The discovery, and distribution locations are svn repositories
grails.plugin.repos.resolveOrder=['myPluginRepository', 'default', 'core']
grails.plugin.repos.discovery.myPluginRepository="http://myServer/svn//my-plugin-distributions"
grails.plugin.repos.distribution.myPluginRepository="http://myServer/svn//my-plugin-distributions"
To publish
grails release-plugin -repository = myPluginRepository

2/ Maven Compatible Repositories (Recommended)
maven-install
The maven-install command will install the Grails project or plugin artifact into your local Maven cache:
grails maven-install

In the case of plugins, the plugin zip file will be installed, whilst for application the application WAR file will be installed.

maven-deploy
The maven-deploy command will deploy a Grails project or plugin into a remote Maven repository:
grails maven-deploy

It is assumed that you have specified the necessary configuration within a pom.xml or that you specify the id of the remote repository to deploy to:
grails maven-deploy --repository=myPluginRepository

The repository argument specifies the 'id' for the repository. You need to configure the details of the repository specified by this 'id' within your grails-app/conf/BuildConfig.groovy file or in your USER_HOMER/.grails/settings.groovy file:
grails.project.dependency.distribution = {
localRepository = "/path/to/my/local"
remoteRepository(id:"myPluginRepository", url:"http://myserver/path/to/repo")
}

The syntax for configuring remote repositories matches the syntax from the remoteRepository element in the Ant Maven tasks. For example the following XML:
<remoteRepository id="myPluginRepository" url="scp://localhost/www/repository">
<authentication username="..." privateKey="${user.home}/.ssh/id_dsa"/>
</remoteRepository>

Can be expressed as:
remoteRepository(id:"myPluginRepository", url:"scp://localhost/www/repository") {
authentication username:"...", privateKey:"${userHome}/.ssh/id_dsa"
}

By default the plugin will try to detect the protocol to use from the URL of the repository (ie "http" from "http://.." etc.), however if you need to explicitly specify a different protocol you can do:
grails maven-deploy --repository=myPluginRepository --protocol=webdav

The available protocols are:

* http
* scp
* scpexe
* ftp
* webdav

Tuesday, October 11, 2011

Arrays Maps List syntax for groovy/ java/ javascript

Slight syntax differences

Note groovy maps are different to json maps, and proposed Java map literals. Grrovy maps use similar syntax to arrays

1/ Groovy syntax

Map
def map= ['id':'FX-11', 'name':'Radish', 'no':1234, 99:'Y']
assert map == ['name':'Radish', 'id':'FX-11', 99:'Y', 'no':1234] //order of keys irrelevant
def map4= [:]
assert map == java.util.LinkedHashMap

def map2= [id:'FX-11', two:"two"] as Hashtable
assert map2 == java.util.Hashtable
assert map2.two == "two"
assert map2['two'] == "two"

Note: key may be string or not.

Array
a= [ 11, 12, 13, 14 ] as Object[]


List (by default create ArrayList)
def list = [5, 6, 7, 8]
assert list.get(2) == 7
assert list[2] == 7
assert list instanceof java.util.List
assert list instanceof java.util.ArrayList

def emptyList = []
assert emptyList.size() == 0
assert emptyList instanceof java.util.ArrayList

// To force to type other than ArrayList use
numbers3 = new LinkedList(['One', 'Two', 'Three', 'Four', 'Five'])
numbers4 = ['One', 'Two', 'Three', 'Four', 'Five'] as Stack // Groovy 1.6+

Note Groovy also has Range type. This is inherits from java.util.List, but is a pure groovy class (e.g. groovy.lang.IntRange)

2/ Java (8) syntax (Note these produce immutable items)
http://sellmic.com/blog/2011/07/08/7-new-cool-features-in-java-7/
http://blog.joda.org/2007/02/java-7-list-and-map-literals_6278.html
http://code.joejag.com/2009/new-language-features-in-java-7/

Map
Map map = {"key" : 1};
int value = map["key"];

Set set = {"item"};

Array
String[] array = {"item1", "item2",}

List
List list = ["Abba", "Beatles", "Corrs"];
List emptyList = [];

3/ Javascript/ Json Syntax

Array
var emptyList = [];
var homogenousList = [1, 2, 3];
var heterogenousList = ["one", 2, 3.0];
Var list = new Array();
list[0] = "item";
list[1] = "item1";

List
Use Array

Map
var emptyMap = {};
var homogenousMap = {"one": 1, "two": 2, "three": 3};
var heterogenousMap = {"one": 1,
"two": "two",
"three": 3.0};

map = {'key':'value'}
map.key == 'value'
map['key'] == 'value'

Monday, October 10, 2011

Grails (hibernate) "Could not find a setter for property in class"

When working on a Domain class (in grails) I wanted to add a convenience method to return some information.

e.g. I had a property endDate, and I wanted to have a method isActive to return true if the endDate does not exist or is in the future.

boolean isActive(){
if(endDate==null) return true;
return endDate
}


However when I try to run the app I get

Solution is

def isActive(){
if(endDate==null) return true;
return endDate
}


If defined as boolean (or int string etc), then Hibernate interprets it as a getter, and will look for corresponding setter, and throw an exception when not finding it.
Defined as with a def, means this won't happen.
Alternative is to set it in the transients static.

e.g.
static transients = [ "active" ]
http://grails.1312388.n4.nabble.com/Transient-properties-td1345135.html

Saturday, October 08, 2011

No Sql

This video is useful

At a high level there are 4 cetegories of noSql Db's


Key Value based e.g. Amazon Riak, Voldemort
Column based e.g. HBase, Bigtable. each row can have its own schema (semi structured)
Document Databases (e.g. couchDb, mongoDb).. Key Value based
Graph based: