Wednesday, September 26, 2012

Grails, GORM, lazy loading one-to-one

I spent all yesterday evening trying to figure out a way to lazy load a one-to-one relationship. At first glace, this probably looks like an academic exercise. However, I have a very pragmatic reason for needing to lazy load a one-to-one relationship.

I have Property and PropertyDetail Domain Classes. 

For now, I am storing images in the database.

Long-term, I am going to look at using Amazon S3 for storing images, but for a personal project where I am still learning, it seems like a decent compromise.

class PropertyDetail {

    static constraints = {
        description type: 'text'
    }

    static belongsTo = [property : Property]

    String description
    byte[] imageMain
    byte[] image1
    byte[] image2
    byte[] image3
    byte[] image4
    byte[] image5
}

I am going to have a list page for Property domain class.

I definitely do not want to take the hit of pulling the PropertyDetail class, not with the images stored in the database.

I hit a wall late evening, when I discovered the following Jira Issue: GRAILS-5077 hasOne mapping is by default eager and cannot be changed to lazy.

However, this is an older JIRA issue, and I did see on the recent Grails 2.1.1 documentation information on doing lazy one-to-one. http://grails.org/doc/latest/guide/GORM.html#manyToOneAndOneToOne

My new plan is to:

  1. Try the approach documented for Grails 2.1.1.
  2. Turn on SQL logging
        datasource { 
            ... 
            logSql = true 
        } 
    

  3. If that does not work, drop back and remap this relationship as a many-to-one.

Saturday, September 15, 2012

Adventures with Grails and Spring Security

Well, I had initially started down the path of creating my own User/Role security model for a Grails App I am building at home in the evenings/weekends.

However, I gave it a little more thought and going back to the "why re-invent the wheel" philosophy of development and just started looking into leveraging Grails Spring Security Plugin.

Found this great article on quick start with Spring Security: http://sysgears.com/articles/spring-security-grails-plugin-quick-start-and-some-tips

Here's what I've done thus far:

1. Modify my BuildConfig.groovy to include Spring Security:


    plugins {
        build ":tomcat:$grailsVersion"
        compile ":spring-security-core:1.2.7.3"
        compile ":twitter-bootstrap:2.1.1"
        compile ":resources:1.1.6"
        runtime ":hibernate:$grailsVersion"
    }

2.Run s2-quickstart:

    s2-quickstart com.philiptenn.security User Role Requestmap

3. Refactored the generated Controllers LoginController and LogoutController so that they are in the com.philiptenn.security package. 

4. Customized Password algorithm to SHA-512:

grails.plugins.springsecurity.password.algorithm='SHA-512'

I feel like this is just scratching the surface. I ended up running into questions and needed to post on StackOverflow: Grails Spring Security Custom UserDetailsService (goal of email in place of username).

Monday, September 10, 2012

Technology Stack

It's late Monday evening, and I'm working on a new personal development project. 

I think I've selected my technology stack:
  • Twitter Bootstrap 2.1.1
  • Grails 2.1.0
  • MySQL 5.5
I find Grails to be rather amazing because it is, for all intents and purposes, a complete stack.  It even has a Twitter Bootstrap plug-in, as well as MySQL Connector/J plug-in, so I guess I could technically say that my technology stack is "Grails".

When working on Java / Java EE projects, I've grown so accustomed to saying "My technology stack is jQuery/JSP/Taglib/Struts/EJB3/Spring/Hibernate/Oracle". 

It feels pretty neat to say "My technology stack is Grails". 

Since I am looking at eventually hosting in a PaaS environment, I am not really concerned about details like OS and Application Server.

However, for my own development environment I am using the following:
  • Windows 7 (thought about switching to Fedora 17 KDE, decided not to take hit on installing a whole new OS).
  • Tomcat 7.0.30
I've made the mistake in working on past personal projects during nights/weekends and getting too caught up in technical details and not focused enough on building a product. 

Grails BuildConfig.groovy: dependencies vs plugins

I am configuring BuildConfig.groovy for a test/sample project.

One item I have always found a bit confusing is the question of the dependencies closure block vs the plugins closure block.

There are times where I have seen that a library could be specified in either.  Also, the version of library would be different.  

For example, the following dependencies closure is provided out of the box with Grails 2.1.0:

    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

        // runtime 'mysql:mysql-connector-java:5.1.20'
    }

Obviously, this leads me to conclude that if I need MySQL Connector/J support, all I have to do is uncomment that line.

However, I have also successfully gotten MySQL Connector/J support by doing the following (I have verified this works):


    plugins {
        compile ":mysql-connectorj:5.1.12"
        compile ":searchable:0.6.3"
        build ":tomcat:$grailsVersion"
        build ":hibernate:$grailsVersion"
        runtime ":database-migration:1.1"

    }

I found the following Nabble post from Graeme Rocher explaining the difference of plugins {} vs dependencies {} blocks

Graeme states:

plugins { } block is used declare dependencies on grails plugins found
in the portal (http://grails.org/plugins/) and built locally.

dependencies { } block is used to declare dependencies on JAR files
and third party java libraries typically found in Maven central (see
http://search.maven.org/#browse)


This made sense to me.  What it did not answer is when I am able to obtain a library via either, which is preferable, if there is a "best practices" or "recommended" approach. 

Knowing that I can get my MySQL Connector/J library from either one (I am certain I would not want to do both), I would just be curious as to which approach is better.