I work on Smith and Ledbrook Grails in action. The examples in the book were written against Grails 1.1 and Hibernate 1.1 (according to the downloaded application.properties source code).
One example is a hubbub. I have Grails 2.0.3 on my machine. I created my own copy of the application using the "grails create-app hubbub", created my domain classes and tests using the Grails commands, and then typed the source in the book. In other words, I am not trying to run the source tree that was created using Grails 1.1 in Grails 2.0.3. Grails 2.0.3 generated all configurations and classes that are not unique to the example. I just typed a small number of sources in an example that Grails did not create in the first place.
Here's my problem - one of the integration tests uses the save () method to save objects. When I run the test and contains only one save (), it succeeds. If the test contains more than one save () method, all calls to save () after the first failure:
| Failure: testSaveAndUpdate(com.grailsinaction.UserIntegrationTests) | groovy.lang.MissingMethodException: No signature of method: com.grailsinaction.User.save() is applicable for argument types: () values: [] Possible solutions: save(), save(boolean), save(java.util.Map), wait(), any(), wait(long) at com.grailsinaction.UserIntegrationTests.testSaveAndUpdate (UserIntegrationTests.groovy:46)
I reordered the save () calls, and the first always works, and subsequent calls always fail. I commented on the tests to run each call to save on their own, and everyone can succeed on their own.
Here is the class I call the save () method on:
package com.grailsinaction class User { String userId String password String homepage Date dateCreated static constraints = { userId(size: 3..20, unique: true) password(size: 6..8) homepage(url: true, nullable: true) }
Here's an integration test that calls save () for the user:
package com.grailsinaction import grails.test.* class UserIntegrationTests extends GrailsUnitTestCase { void testFirstSaveEver() { def user = new User(userId: 'joe', password: 'secret', homepage: 'http://www.grailsinaction.com') assertNotNull user.save() assertNotNull user.id def foundUser = User.get(user.id) assertEquals 'joe', foundUser.userId } void testSaveAndUpdate() { def user = new User(userId: 'joe', password: 'secret', homepage: 'http://www.grailsinaction.com') assertNotNull user.save() def foundUser = User.get(user.id) foundUser.password = 'sesame' foundUser.save() def editedUser = User.get(user.id) assertEquals 'sesame', editedUser.password } }
This is the data configuration from my generated DataSource.groovy (all environments, but the test has been edited for brevity):
dataSource { pooled = true driverClassName = "org.h2.Driver" username = "sa" password = "" } hibernate { cache.use_second_level_cache = true cache.use_query_cache = false cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' } // environment specific settings environments { development { ... } test { dataSource { dbCreate = "update" url = "jdbc:h2:mem:testDb;MVCC=TRUE" } } production { dataSource { ... } } } }
Here is the original from the book:
dataSource { pooled = true driverClassName = "org.hsqldb.jdbcDriver" username = "sa" password = "" } hibernate { cache.use_second_level_cache=true cache.use_query_cache=true cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider' } // environment specific settings environments { development { dataSource { ... } } test { dataSource { dbCreate = "update" url = "jdbc:hsqldb:mem:testDb" } } production { dataSource { ... } } }
The big difference that jumps out is that the original driver is org.hsqldb.jdbcDriver, while one Grails 2.0.3 uses org.h2.Driver. Another major difference is that the source URL of the data source is jdbc: hsqldb: mem: testDb, and the new one is jdbc: h2: mem: testDb; MVCC = TRUE. Finally, these caching mechanisms are slightly different.
Could this be a configuration issue that should do something with the differences between h2 and hsqldb? If so, what is the best place for me to understand what I need to do to get this to work?