Saturday, February 16, 2013

Database-Pattern 1: Property-Group

There are times when you create a complex domain class where you might come up with code like this:

User.groovy
class User {
  String name
  String email
  String addressStreet
  String addressZip
  String addressCity
}

ok. I guess this is obvious - there should be another data type 'Address' to hold the three address properties. Something like

User.groovy
class User {
  String name
  String email
  Address address
}
Address.groovy
class Address {
  String street
  String zip
  String city
}

but isn't this waste? How many users will share the same address? The answer is most of the time zero. So why do we create another domain class for that? Do we need to store the data in another table? It looks cleaner, but IMHO Grails has a more elegant concept for domain classes like that:

User.groovy
class User {
  String name
  String email
  Address address
  static embedded = ['address']
}

class Address {
  String street
  String zip
  String city
}

Notice that this time, we only have one file with two classes. The 'embedded' definition ensures that both classes are stored in one table. Grails calls this 'Composition'

There is only one drawback: the scaffolding does not take the composite properties into account. And the composite properties break the generated create-view.

Let's rename this blog

When I started this blog, I though the name was a good idea - one blog for one purpose. With lots of effort and motivation, I wrote the first entries. But I soon noticed that the topic isn't too interesting: relational databases are supported very well by Grails. Others are supported, but they are not the kind of database Grails was written for. So I stopped writing posts.

Later I added one off-topic post which got the most comments. And I am still doing lots of Grails development and would have lots of ideas to write down ... if I would have more time and the blog another name.

That's why I now change the name some something different. Maybe it will change a cuple of times during the next days - we'll see...

Just for the records: the old name was "Seven Databases used with Grails (in seven Weeks)"

I would like to start the new theme with some database patterns for Grails which I use often...

Friday, August 10, 2012

Off-Topic: Groovy and Grails on Raspberry Pi

It works! Received my Raspberry Pi this week and had to see if it runs Java, Groovy and Grails.

The ressources (256MB memory) of the Raspberry are very limited, so I didn't really expect to make it work, but instead it was easy.

a simple

apt-get install openjdk-7-jdk

installs java. The same for groovy:

apt-get install groovy

It takes some seconds until the groovy shell starts up, but it makes a good impression.

Installing Grails was a little bit harder since it can't be installed through apt-get. But a

wget http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.0.4.zip
unzip grails-2.0.4.zip

nearly did the job. You still have to set some environment variables and lower the memory needs through GROOVY_OPTS (I personally changed the settings directy in the startGroovy). After that it works! Slowly, but it works. Generating a page takes aprox 6 minutes :-)

Sunday, June 24, 2012

Week 4 / Day 2: Last Chance for CouchDB

Never give up, never surrender.

I give CouchDB another chance. When you experience problems with open source software, you should at least create some bug entries in order to tell the developer that something does not work.

So I searched for the grom-couchdb bugtracker and stumbled upon the code base on git. Hm. It looks like some files are newer than what I've got... And there seems to be even a patch for the 2.0 problem!

https://github.com/coryhacking/gorm-couchdb
=> https://github.com/MalteJ/gorm-couchdb/tree/

but now that I've take a look at the issue tracker, I see that it would be too much work to do in order to get it up and running: this issue explains inderectly, that the plugin needs a js-view in order to work and it is not generated if you do a generate-all on a no-couch domain.

It seems that you may use the plugin if you already have a better knoledge of couchDB, but for me, that's it. No couchDB for my grails project!

Friday, June 15, 2012

Week 4 / Day 1 CouchDB

Today I did some experiments with CouchDB. The daabase is easy to install, has a clean web interface and makes jsut a good expression.

So I searched for a Grails plugin and found a 2 years old one: Grom-CouchDB.

Installing the plugin wasn't easy. I first tried my Grails 2.0.x installation - it easily picks up the plugin, but when I try to run it, I get a strange compilation error:

user@ubuntu:~/grails/couch3$ grails run-app
| Compiling 53 source files.
| Error Compilation error: startup failed:
Compile error during compilation with javac.
/home/user/.grails/2.0.4/projects/couch3/plugins/gorm-couchdb-0.9.2/
src/java/org/codehaus/groovy/grails/plugins/couchdb/domain
/CouchDomainClass.java:49: 
error: CouchDomainClass is not abstract and does not override 
abstract method getPersistentProperty(String) in GrailsDomainClass
public class CouchDomainClass extends AbstractGrailsClass implements
ExternalGrailsDomainClass {
       ^
/home/user/.grails/2.0.4/projects/couch3/plugins/gorm-couchdb-0.9.2/
src/java/org/codehaus/groovy/grails/plugins/couchdb/domain
/CouchDomainClassProperty.java:37: 
error: CouchDomainClassProperty is not abstract and does not 
override abstract method isDerived() in GrailsDomainClassProperty
public class CouchDomainClassProperty implements 
GrailsDomainClassProperty {
       ^
Note: /home/user/.grails/2.0.4/projects/couch3/plugins/
gorm-couchdb-0.9.2/src/java/org/codehaus/groovy/grails/plugins/
couchdb/domain/CouchDomainClass.java uses or overrides a 
deprecated API.

Not a good start. Especially when I can't imagine that Grails 1.3.x should not bring up the same exception. Nevertheless, I'll give it a try.

Somehow, I really ran into problem when I even just tried to install the plugin with Grails 1.3.x. The plugin is in the list when I do a <pre>grails install-plugin gorm-couchdb</pre> but when the script runs, it tells me that it can't find the plugin.

So I tried to download and install it but I've got the same result. So I made use of my last special trick: I copied and renamed the downloaded zip:
cp gorm-couchdb-0.9.2.zip grails-gorm-couchdb-0.9.2.zip
and tried to install it:
grails install-plugin grails-gorm-couchdb-0.9.2.zip
It is very interesting, that if you try to install it with the grails-prefix, it seems to pick up the file without the prefix. But it does not work the other way around. Another interesting thing is that I only ran into this problem on my linux machine. Netbeans managed to install it without any problem. I guess that this is fixed in Grails 2.0.x

Ok. So now, we have an installed plugin. If you read through the documentation, you'll find that you don't have to remove the hibernate plugin. Even better, you can configure that plugin to use anotation in order to mix hibernate and couchDB. But beware: if you want to make use of
grails generate-all domain
You first have to execute this script and only afterwards anotate your domain class - otherwise it will tell you that it can't map your domain:
Running script /usr/share/grails/1.3.8/scripts/GenerateAll.groovy
Environment set to development
Domain class not found in grails-app/domain, trying hibernate 
mapped classes...
No domain class found for name sevendatabases.DataTypes. Please 
try again and enter a valid domain class name
Application context shutting down...
Application context shutdown.
By working around this, I managed to setup my test project, but unfortunately, as soon as I try to access the list controller, I get the following Exception:
org.jcouchdb.exception.DataAccessException: error querying view: code 404
 at org.jcouchdb.db.Database.queryViewInternal(Database.java:848)
 at org.jcouchdb.db.Database.queryView(Database.java:656)
 at org.jcouchdb.db.Database$queryView.call(Unknown Source)
 at org.jcouchdb.db.Database$queryView.call(Unknown Source)
 at sevendatabases.DataTypesController$_closure2.doCall(DataTypesController.groovy:13)
 at sevendatabases.DataTypesController$_closure2.doCall(DataTypesController.groovy)
 at java.lang.Thread.run(Thread.java:722)
So, that's it for now. I guess this problem is beacuse I use the current version of CouchDB, but it makes no sense for me to downgrade to a 2 year old version just to make the plugin work.
For me, CouchDB seems to be great, but there is no easy way to use it with a standard Grails CRUD application... :-(

Sunday, June 10, 2012

Transactions

I knew that it would take more than 7 weeks to write this blog :-)

Today I would like to focus on another aspect of those databases - how do they handle transactions?

For an RDBMS it is quite common to support transactions, but I haven't read about transactions in the 7db7w book yet that those key-value databases support them.

Let's write a test for transactions:

package sevendatabases

import static org.junit.Assert.*
import org.junit.*

class TransactionTests extends GroovyTestCase {

    static transactional = false; // 1
   
    void setUp() {
    }
   
    @Test
    void testSomething() {
        def numBooks = Book.count()
        Book.withTransaction { status ->
            new Book (name:'test',isbn:'test').save(flush:true,failOnError:true)
        }
        assert Book.count() == numBooks+1
        Book.withTransaction { status ->
            new Book (name:'test',isbn:'test').save(flush:true,failOnError:true)
            status.setRollbackOnly()
        }
        assert Book.count() == numBooks+1
    }
}


Have you noticed the line marked with "// 1"? In grails, integration tests are executed in a transactional context by default. This causes some problems while testing the transaction itself. So I disabled the default transactional context.

Now I run this test against all of my configured databases:

MS SQL Server: works
MySQL: works
Oracle Express: works
Riak: fail! No transactionManager bean configured

...ok. I could have used the overview chart from the book to get the same results. But this way I had to figure out how to test transactiosn ins Grails :-)

Saturday, June 2, 2012

MS SQL Server Express

Shame on me! I forgot to include the MS SQL Server Express in my comparison!

But as any RDMS, MS SQL Server Express seems to be no problem. Installing it is easy, getting the jdbc-driver is easy, too. Connecting is a little bit hards, but you'll find enough resources on the web. Hint: I had to activate the TCP-Connection and h ad to disable the dynamic ports.

After getting the connection ready, the reast was easy - everything works as expected. Here is the updated comparison table:


PropertyMySQLPostgreSQLOracle EXMS SQL
myBigString varchar(4000) character varying(4000) VARCHAR2(4000)varchar(4000)
myBigString2 varchar(4000) character varying(4000) VARCHAR2(4000)varchar(4000)
myBigdecimal decimal(19,2) numeric(19,2) DECIMAL(19)nummeric(19,2)
myBinaryData tinyblob bytea LONGVARBINARYimage
myBoolean bit(1) boolean DECIMAL(1)tinyint
myDate datetime timestamp without time zoneTIMESTAMP(7)datetime
myDouble double double precision FLOAT(126)float
myFloat float real FLOAT(126)float
myInList varchar(5) character varying(5) VARCHAR2(5)varchar(5)
myInteger int(11) integer DECIMAL(10)int
myString varchar(255) character varying(255) VARCHAR2(255)varchar(255)
myString80 varchar(80) character varying(80) VARCHAR2(80)varchar(80)