Archive

Archive for the ‘Grails’ Category

Keep things where you can see stuff for grails projects

January 26, 2015 Leave a comment

Been having issues with a plugin project i’ve been trying to mend. This has led to exploration round plugins, gant scripts etc.

The latest one has been relating to gant script caching – when i added some script and got and error. So i removed the lines – and the cached version of the script with the error continues to being run. Not sure why. However short term quickfix is delete the script cache between calls

however on the way to finding the script cache and clearing it out – i’ve trod where others have been. One of the things that is a good thing to do is to update your conf/buildConfig.grooy file up at the top and add this little line

grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
grails.project.test.reports.dir = "target/test-reports"
grails.project.work.dir = "target/work" //add this line :where default work is stored

by default grails stores all the project work in .grails/.. This is not immediately obvious to newbies. by setting the work.dir inside your project – its easy to go looking and understand what the framework might be doing behind the scenes.

having the added the line, in GGTS select your project, right click and do Grails tools/Refresh dependencies

when you do that you’ll notice that the plugins are ‘re fetched’ and added in this case to the /target/work directory

Starting process on BTP055237/10.109.112.186
Loading Grails 2.4.4
|Configuring classpath
.
|Environment set to development
......
|Installing zip release-3.0.1.zip...
...
|Installed plugin release-3.0.1
.............
|Installing zip rest-client-builder-1.0.3.zip...
...
|Installed plugin rest-client-builder-1.0.3
..................
|Compiling 13 source files
.......
|Compiling 4 source files

this creates the work directory in your project like this

grails-work

when you run a script the compiled copy goes into the scriptCache as shown. However there is is an issue in the current grails2.4.4 where if you update the script after first running it, the script cache doesn’t update to the later groovy script you just saved. The tactical way round this (brute force) is to call the clean-all script which releases the GGTS lock on the closure, cleans the cache and you can then re-run the script which will recompile and recache. Bit painful but seems to work, without having to restart GGTS each time!

Advertisements
Categories: Grails, Grails Plugin Tags:

another silly gotcha grails 2.4 and plugin development with integration testing

November 15, 2014 Leave a comment

just wasted an hour getting the to the bottom of this. Hope this saves you some of that.

i just created a new Grails plugin project using grails 2.4.4 using GGTS. Plugin project gets created fine.

I created a couple of domain classes and tried to run an integration test.

hah first point. The grails documentation hasn’t caught up with what the code does. The documentation for unit tests still refers to extending the GroovyTestCase. However this is no longer what the code generator assumes you should do. Generating a integration test and you see the class now extends

import grails.test.spock.IntegrationSpec
..
class xxxSpec extends IntegrationSpec {

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() { 
    }
}

slightly annoying point is that spoc which is the default test runner assumes that you have the
when :, then:, expect: or similar blocks to be happy and the default template generation doesn’t do this for you. as a Newbie this can catch you out if you try and run tests.

however the key waste of time today was with a new plugin project. By default the plugin project doesn’t load the hibernate plugin in buildConfig.groovy. When you run your integration test it throws a weird error along the lines of


java.lang.IllegalStateException: Method on class [Domain class] was used outside of a Grails application

which throws you completely. What says you? of course i’m running grails that’s integration tests do for you. The answer is that missing hibernate plugin which causes the problem. I eventually found this on stackoverflow .

add the runtime plugin for hibernate in buildConfig and off you go

there are it appears other issues when using functional testing – but i’ve not got that far. part of the resolution to that requires you to include another plugin : remote-control plugin. I’ve included the link here as i’m bound to need it later

There is another bug also hibernate4 4.3.6.1 doesn’t inject the dateCreated, lastUpdated Dates automatically. you have to roll back to 4.3.5.5 and then it works as expected in integration tests

new Grails App : Annoying gripe and time waster : create-drop with default h2 db

September 23, 2014 Leave a comment

fell over this is with latest grails builds GGTS 3.6.1 / grails 2.4.2

if your new to grails what you want to do is quickly add a domain object and try and run some tests quickly etc

instead you get a silly error like this

HHH000389: Unsuccessful: alter table … drop constraint …

and it fails to start. This is frankly annoying and ought to be handled properly – but isn’t fixed yet.

The problem is with in memory DB use and using the create-drop default for hibernate with the H2 drivers. it gets confused as the db doesn’t exist and you can’t drop whats not there .

the easy fix is to override the default H2 dialect. create a file like this in your src/groovy (or java) folders

package com.softwood;

import org.hibernate.dialect.H2Dialect;

/**
 * Workaround.
 * 
 * @see https://hibernate.onjira.com/browse/HHH-7002
 * 
 */
public class ImprovedH2Dialect extends H2Dialect {
    @Override
    public String getDropSequenceString(String sequenceName) {
        // Adding the "if exists" clause to avoid warnings
        return "drop sequence if exists " + sequenceName;
    }

    @Override
    public boolean dropConstraints() {
        // We don't need to drop constraints before dropping tables, that just
        // leads to error messages about missing tables when we don't have a
        // schema in the database
        return false;
    }
}

then in your conf/DataSource.groovy add this line at the top of the file

dataSource.dialect = com.softwood.dialects.ImprovedH2Dialect

then re-run the grails run-app and the problem should disappear

this never used to happen so they ought to provide a fix for it as its very easy to put off new entrants from getting started

alternatively you can set the dbCreate = “update” which avoids the drop call on the empty in memory db

pretty annoying and hope this sames someone some heartache wondering what to do next

Categories: Grails Tags: , ,

Groovy 2 asType conversation

August 13, 2014 Leave a comment

Groovy enables you to provide overload a method “asType (Class clazz)”. However i had some difficulty with this relating to duck typing which didn’t work. Not entirely sure why.

i’d been trying to use a grails app with joda date – LocalDate, and new java8 LocalDate. however the java8 version kept crashing when i ran a test – so i dropped back to java 7 and Joda package.

Hibernate doesn’t seem to handle Joda/Java LocalDates (havn’t tried this very far). So i kept it simple i created a Birthday Domain Class with three int params (year, month,date) and wanted to ensure i could generate a LocalDate from this.

first attempt was try this using duck typing

	Object asType (clazz) {
		if (clazz == LocalDate) {
			new LocalDate (year, month, day)
		}
		else {
			super.asType(clazz)
		}

	}

however this wouldn’t fire when i tried

def bday = new Birthday (year:1962, month:10, day:20) as LocalDate

and it said it couldn’t handle the caste at runtime – odd.

eventually tried and explicitly set the type for the method and then it ran successfully and did the dynamic caste

	Object asType (<strong>Class</strong> clazz) {
		if (clazz == LocalDate) {
			new LocalDate (year, month, day)
		}
		else {
			super.asType(clazz)
		}

	}

adding the explicit type did it

Categories: Grails, Groovy Tags:

On Grails Neo4j and unit integration testing …

March 22, 2014 Leave a comment

Life is never as easy as you imagine …

So first get your grails environment set up, i’m using GGTS 3.5M2 and grails 2.3.7

Create yourself a grails project and wait for all the scripts to finish. Then in your projects /conf/BuildConfig you need to the add the following plugin -> :neo4j:1.1.1, and whilst your at it you need to comment out the database-migration plugin as there is a bug somewhere that stops your integration tests from running. ( i have left the hibernate plugin installed as i am setting the static mapWith clause on the domain classes i want to persist through Neo4j (trying mixed mode persistence and see what happens))

   plugins {
	compile ":neo4j:1.1.1"
		
        // plugins for the build system only
        build ":tomcat:7.0.52.1"

        // plugins for the compile step
        compile ":scaffolding:2.0.2"
        compile ':cache:1.1.1'

        // plugins needed at runtime but not for compilation
        runtime ":hibernate:3.6.10.9" // or ":hibernate4:4.3.4"
        //runtime ":database-migration:1.3.8"
        runtime ":jquery:1.11.0.2"
        runtime ":resources:1.2.7"
        // Uncomment these (or add new ones) to enable additional resources capabilities
        //runtime ":zipped-resources:1.0.1"
        //runtime ":cached-resources:1.1"
        //runtime ":yui-minify-resources:0.1.5"

        // An alternative to the default resources plugin is the asset-pipeline plugin
        //compile ":asset-pipeline:1.6.1"

        // Uncomment these to enable additional asset-pipeline capabilities
        //compile ":sass-asset-pipeline:1.5.5"
        //compile ":less-asset-pipeline:1.5.3"
        //compile ":coffee-asset-pipeline:1.5.0"
        //compile ":handlebars-asset-pipeline:1.3.0.1"
    }

also we’ll start with embeddedGraphDatabase mode – but you still need to inform grails where the backing store is in /conf/DataSource.groovy – else it’ll moan saying it can’t find grails.neo4j configuration if you don’t do this. The directory you point the database in must be writable on your local machine. I added mine just above the environments section in DataSource.groovy like this

grails {
	neo4j {
			type = "embedded"
			location = "users/802518659/Documents/data/neo4j"
			params = []
	}
}
...

The plugins user guide can be found here

With that in place – your ready to go. You start as normal and write a domain class – say something like this. Note the mapWith clause to tell grails to use Neo

domain:com.softwood.interaction.groovy

class Interaction {

String name
//List tasks //declared i wanted a list not a set

static hasMany = [tasks: Task]

static mapWith = “neo4j”

static constraints = {
name nullable:true
}
}
[/sourcode]

Now some quick notes on testing. When you create a domain class GGTS will automatically create a spoc unit test for you (new default in GGTS).

So now some more fun. Spoc is great, and i’ll post something separately about spoc and grails.

For now you need to know a couple of things (and i forgot of course). Grails does lots of Dynamic additions to your domain classes – so what looks simple as you type generates a complex class with loads of extra ‘Grails’ goodness including addTo() methods if you have a one to many defined on the one side.

However, in unit testing mode this embellishment does not take place and you pretty much get your plain POJO. This can be confusing as you imagine that this embellishment always happens. It does in integration and real running (the grails framework is brought up for both ) but not in unit testing

so if you write a test like this for the domain class like this

unit test:InteractionSpec

@TestFor(Request)
@Mock (Task) // add this to Mock the collaborator class
class RequestSpec extends Specification {
..
void “test create”() {
given:

Interaction req = new Interaction (name:”job1”)

when:
assertTrue req.validate()
req.save (flush:true) //

def task1 = new Task (name: ‘new task’)
assert task1
assert task1.validate()

req.addToTasks (task1) //fails unit test – cant find addToTasks method

[/sourceocde]

Most disconcerting, So whats going on. Its a unit test so that extra goodness hasn’t been added. This is what i’d forgotten. If you look in the manual it shows you about unit testing a controller say and using the @Mock ([…]) for the domain collaborators. But here your trying to unit test the domain class itself.

Once you get that then there are two ways round it. One the brute force path, is to do the work manually like this

...
		req.tasks = new HashSet()
		task1.job = req
		req.tasks.add (task1)
		req.save(flush:true ) //often have to flush this in unit test else grails wont write immediately

However this is alot of extra work. The other approach is to use the @Mock ([…]) after the @TestFor () like this, and add the domain class and any collaborator classes to the array of classes to Mock. You’ll now note that the respondsTo method assertion now passes, and the whole test will pass.

@TestFor(Interaction)
@Mock ([Interaction, Task])
class InteractionSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test create"() {
				
		given: 
		def interaction = new Interaction (name: "first job")
		def task1 = new Task (name:"task1")
		def task2 = new Task (name:"task2")
		
		when:
		assert interaction.respondsTo ("addToTasks")
		def res =   interaction.save (flush: true)
		Interaction thing = Interaction.get (1)
		thing.addToTasks (task1)
		thing.addToTasks (task2)
		
		def tasks = thing.tasks.collect{it.name}.sort()
		
		then:
		assert thing.name == "first job"
		assert thing.tasks.size() == 2
		assert ["task1", "task2"] == tasks
		
    }
}

Basic Gorm Relationship Mappings

February 9, 2014 Leave a comment

I’ve placed a word document with UML pictures to show what happens on the database for various relationship mappings. Its not always obvious what you get and when in the configuration so i’ve tried to show in summary form what happens when you drive the model

Gorm Basic Model Mappings

Hope this makes sense for others

Categories: Grails Tags: , ,

How to get Grails log output in unit testing

February 6, 2014 Leave a comment

Spent some time struggling with getting grails to produce output from logging when running unit and integration tests

read the documentation and tried various stuff to no avail. Then i spotted something silly i’d done (i had def setup () and def teardown () methods – which don’t get called. They needed to be void setUp(), and void tearDown())

having fixed this my code started to get called.

grails injects a log property into unit tests which is of type java.util.logging.Logger. In the GGTS console this prints out in red.

if you don’t want the injected log you can get one directly using one of the logger factories (either apache, or sl4j) like this

package com.softwood

import grails.test.mixin.*
import grails.test.mixin.domain.DomainClassUnitTestMixin

import org.neo4j.graphdb.GraphDatabaseService

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.apache.commons.logging.LogFactory

@TestMixin(DomainClassUnitTestMixin)
class DomainTests {
	GraphDatabaseService gdb
	static Logger sllog = LoggerFactory.getLogger(DomainTests)
	def alog = LogFactory.getLog(getClass())
	
	void setUp () {
		log.info "java util: hello William : " + log.class 
		assert sllog.isInfoEnabled() 
		sllog.info "sl4j: getting gdb bean : " + sllog.class
		alog.info "apache: getting gdb bean : " + alog.class
	}

you’ll notice the assert on one of the loggers – this is checking that Info logging is enabled.

you control that by ensuring that the log4j section in grails-app/conf/config.groovy is set correctly. This is described in section 4.1.2 of the grails users guide.

you have to explicitly set the level in order to see the output. The logger will print from the level and any above. My default configuration from the project create didn’t include any “Info” logging so i added the last line – info ‘com.softwood’

if you remove this – then the assert previously noted will fail

I didn’t need to uncomment out the root section – though you can, it sets the default behavior for the root logger that the others inherit

// log4j configuration
log4j = {
    // Example of changing the log pattern for the default console appender:
    //
    appenders {
        console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
    }
	
	//set default root logger behaviour for the system - use info and send to console appender
	/*
	root {
		error    'stdout'
		additivity = true
	} */


    error  'org.codehaus.groovy.grails.web.servlet',        // controllers
           'org.codehaus.groovy.grails.web.pages',          // GSP
           'org.codehaus.groovy.grails.web.sitemesh',       // layouts
           'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
           'org.codehaus.groovy.grails.web.mapping',        // URL mapping
           'org.codehaus.groovy.grails.commons',            // core / classloading
           'org.codehaus.groovy.grails.plugins',            // plugins
           'org.codehaus.groovy.grails.orm.hibernate',      // hibernate integration
           'org.springframework',
           'org.hibernate',
           'net.sf.ehcache.hibernate'
		   
	info   'com.softwood' 
	
}

having done this when you now run your test – and i didn’t need to -echoOut to the test-app -unit , you’ll see your output print to the console

the explicit loggers generate black text output – and have slightly less decoration than the default injected log

|Configuring classpath
.
|Environment set to test
...................
|Compiling 1 source files
.................................................................
|Running 1 unit test...
|Running 1 unit test... 1 of 1Feb 06, 2014 10:49:24 PM java_util_logging_Logger$info call
INFO: hello William : class java.util.logging.Logger

softwood.DomainTests getting gdb bean : class org.slf4j.impl.GrailsLog4jLoggerAdapter
softwood.DomainTests a: getting gdb bean : class org.apache.commons.logging.impl.SLF4JLog
|Completed 1 unit test, 0 failed in 0m 3s
.
|Tests PASSED - view reports in C:\Users\802518659\Documents\temp (not backed up)\grails 3.3 workspace\TestNeo4jGrails235\target\test-reports

so now we are back on track and you can see some output when you run your unit tests – not just whether the asserts pass or fail quietly

note: when you do an integration test the log that’s injected by Grials by default is now of type class org.apache.commons.logging.impl.SLF4JLog

also integration tests don’t use the unit test mixins so you just extend your test class from GroovyTestCase.

good testing …

%d bloggers like this: