Tuesday, August 2, 2011

"Slash n" in db migrations scripts in Grails

If it is needed to print \n from migration script, it is needed to write 4 slashes before n (1, 2 or 3 will just print new line symbol), so it should look something like:

  changeSet(author: "user", id: "1") {
    insert(tableName: "table") {
      column (name:'column', value:'''aaaa\\\\nbbbb''')
    }
  }


will result in value being -

aaaa\nbbbb

Monday, August 1, 2011

Cannot delete parent object in GORM

Sometimes, when trying to delete parent object in GORM, even when there is children cascade:'all-delete-orphan' there is exception:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`db`.`domain`, CONSTRAINT `FKB8FB823DBF953235` FOREIGN KEY (`domain_id`) REFERENCES `user` (`id`))
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.Util.getInstance(Util.java:384)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2113)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2409)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2327)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2312)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)

It is possible to solve this issue, by explicitly clearing all children from parent object before delete.

    domain.children.clear()


After that it successfully deletes domain object.

Sunday, July 31, 2011

NoSuchElementException after click() in Selenium 2

Sometimes in Selenium 2 after clicking on some element, it does not execute actual click (but does not throws error that element is not found), cann't find element from next page and therefore throws this exception:

Unable to locate element: {"method":"class name","selector":"alert"} For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48' System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24' Driver info: driver.version: RemoteWebDriver

org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"class name","selector":"alert"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: RemoteWebDriver
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:131)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:105)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:405)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:193)
    at org.openqa.selenium.remote.RemoteWebDriver.findElementByClassName(RemoteWebDriver.java:250)
    at org.openqa.selenium.By$ByClassName.findElement(By.java:349)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:185)
    at org.openqa.selenium.WebDriver$findElement.call(Unknown Source)
...
Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException: Unable to locate element: {"method":"class name","selector":"alert"}
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: unknown

First, you should check that there is no element with same selector and it does not tries to click some div. Second, I found that sometimes if there is floating div, especial over your links or buttons, it cann't properly click it. In latter case, best solution for form buttons is to use submit, instead of click, like:
driver.findElement(By.id("update")).submit();
Another thing that helps - especially with links, is to remove overflowing div (closing it - depends on your application logic) and waiting for second, like:
Thread.sleep(1000);

Tuesday, July 26, 2011

How to ignore failed database migrations

When using Grails database migration plugin, failing migrations is sign of some problem - usually some syntax error. But in some cases it is not needed and it is ok to ignore them. For example, I faced this problem while testing application which created db in memory from Hibernate entities. Some particular migrations, like ones dealing with existing records or legacy columns, were failing with no meaning.
Fortunately, there is easy way to ignore some migrations. Just add failOnError:'false' to change set definition and it will report exception in logs, but will continue with loading. There is example:

  changeSet(author: "user", id: "96", failOnError:'false') {
    update(tableName: "table") {
      column(name: "column", valueBoolean: false)
      where ('column is null')
    }
  }


This is good that it is specified per change set, as only these dealing with particular columns will be able to fail, it will be still strict with others. Only way it would be better, if there would be global property, so it would be still strict in production, but more forgiving in test environment.

Unable to locate element in Selenium 2

There is new version of Selenium, which is very good and easy to use, unfortunately there is too little documentation yet. After I started to use it, one of the first issues I found is this:

org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"link text","selector":"Home"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: RemoteWebDriver
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:131)
        at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:105)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:405)
        at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:193)
        at org.openqa.selenium.remote.RemoteWebDriver.findElementByLinkText(RemoteWebDriver.java:218)
        at org.openqa.selenium.By$ByLinkText.findElement(By.java:223)
        at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:185)
        at org.openqa.selenium.WebDriver$findElement.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
        at selenium.run(selenium.groovy:14)
        at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:266)
        at groovy.lang.GroovyShell.run(GroovyShell.java:229)
        at groovy.lang.GroovyShell.run(GroovyShell.java:159)
        at groovy.ui.GroovyMain.processOnce(GroovyMain.java:514)
        at groovy.ui.GroovyMain.run(GroovyMain.java:329)
        at groovy.ui.GroovyMain.process(GroovyMain.java:315)
        at groovy.ui.GroovyMain.processArgs(GroovyMain.java:112)
        at groovy.ui.GroovyMain.main(GroovyMain.java:93)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:108)
        at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:130)
Caused by: org.openqa.selenium.remote.ErrorHandler$UnknownServerException: Unable to locate element: {"method":"link text","selector":"Home"}
Build info: version: '2.2.0', revision: '13073', time: '2011-07-26 00:54:48'
System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_24'
Driver info: driver.version: unknown

even when element is present on the page. After some googling I found easy solution to this issue:

    driver = new FirefoxDriver();
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 

This is default period which Selenium will try to wait for element to appear on the page, before throwing error, and this works perfectly for me.


Saturday, July 23, 2011

MissingMethodException when running test with baseUrl in Grails

Running functional test with baseUrl option can end with exception:

Error executing script TestApp: groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean)
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean) values: [grails.testing.functio
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
        at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:391)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
        at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
        at gant.Gant.withBuildListeners(Gant.groovy:427)
        at gant.Gant.this$2$withBuildListeners(Gant.groovy)
        at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
        at gant.Gant.dispatch(Gant.groovy:415)
        at gant.Gant.this$2$dispatch(Gant.groovy)
        at gant.Gant.invokeMethod(Gant.groovy)
        at gant.Gant.executeTargets(Gant.groovy:590)
        at gant.Gant.executeTargets(Gant.groovy:589)
Caused by: groovy.lang.MissingMethodException: No signature of method: static java.lang.System.setProperty() is applicable for argument types: (java.lang.String, java.lang.Boolean) values: [grails.test
Possible solutions: setProperty(java.lang.String, java.lang.String), getProperty(java.lang.String), getProperty(java.lang.String, java.lang.String), hasProperty(java.lang.String), getProperties(), getP
        at _GrailsTest_groovy$_run_closure11.doCall(_GrailsTest_groovy:366)
        at _GrailsTest_groovy$_run_closure11.doCall(_GrailsTest_groovy)
        at _GrailsTest_groovy$_run_closure1_closure21.doCall(_GrailsTest_groovy:184)
        at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:174)
        at TestApp$_run_closure1.doCall(TestApp.groovy:82)
        at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
        ... 10 more

This can be easily worked around by running tests in interactive mode. Just run:

grails interactive

and you can execute your tests from there like:

test test-app functional: MyTests -baseUrl="http://..."

Apart from that it works, this gives also additional benefits like: you can debug with single attachment from IDE (remember to use grails-debug); also you can run grails application before executing tests which allows to use in-memory db with functional testing.

Monday, July 18, 2011

BLOB and TEXT type for fields in GORM

If you need long type for your fields with GORM automatic table creation, you just need to specify appropriate constraint for that field, like:
description(nullable:true, maxSize:1000000)