Tuesday, May 27, 2008

Ext plugin discontinued



I just want to mention that I decided to discontinue working on the Ext (Scaffolding) plugin for Grails.

The reason is Ext's recent license change (1, 2, 3, 4) to GPL v3. Although the Ext team has announced some Open Source FLOSS exceptions, for me it's end of the line here Ext concerned.

Monday, May 12, 2008

Uber Generate All script for Grails



While I was creating a Grails application on an exsiting database schema I was to lazy to run grails generate-all 15 times. So I created an Uber Generate All script, which generates controllers and views for all domain classes in your application.

If you want to use it create a new script within your application (e.g. grails create-script UberGenerateAll) and copy in the code below:


import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
import groovy.text.SimpleTemplateEngine
import org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator;
import org.codehaus.groovy.grails.scaffolding.*
import org.springframework.mock.web.MockServletContext
import org.springframework.core.io.Resource;

Ant.property(environment:"env")
grailsHome = Ant.project.properties."environment.GRAILS_HOME"

includeTargets << new File ( "${grailsHome}/scripts/Package.groovy" )

generateViews = true
generateController = true

target('default': "The description of the script goes here!") {
    depends( checkVersion, packageApp )
    typeName = "Domain Class"
    doStuff()
}

target(doStuff: "The implementation task") {

    rootLoader.addURL(classesDir.toURL())
    def beans = new grails.spring.WebBeanBuilder().beans {
        resourceHolder(org.codehaus.groovy.grails.commons.spring.GrailsResourceHolder) {
            this.resources = "file:${basedir}/grails-app/domain/**/*.groovy"
        }
        grailsResourceLoader(org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean) {
            grailsResourceHolder = resourceHolder
        }
        def pluginResources = [] as Resource[]
        if(new File("${basedir}/plugins/*/plugin.xml").exists()) {
            pluginResources = "file:${basedir}/plugins/*/plugin.xml"
        }

        pluginMetaManager(org.codehaus.groovy.grails.plugins.DefaultPluginMetaManager, pluginResources)
        grailsApplication(org.codehaus.groovy.grails.commons.DefaultGrailsApplication.class, ref("grailsResourceLoader"))
    }
                                                    
    appCtx = beans.createApplicationContext()    
    appCtx.servletContext = new MockServletContext()
    grailsApp = appCtx.grailsApplication

    grailsApp.initialise()
    def domainClasses = grailsApp.domainClasses

    if(!domainClasses) {
        println "Domain classes not found in grails-app/domain, trying hibernate mapped classes..."    
        try {
            def config = new GrailsRuntimeConfigurator(grailsApp, appCtx)
            appCtx = config.configure(appCtx.servletContext)                
        }
        catch(Exception e) {
            println e.message
            e.printStackTrace()
        }
        domainClasses = grailsApp.domainClasses
    }
    
    if(domainClasses) {
        def generator = new DefaultGrailsTemplateGenerator()
        domainClasses.each { domainClass ->
            if(generateViews) {
                event("StatusUpdate", ["Generating views for domain class ${domainClass.fullName}"])                
                generator.generateViews(domainClass,".")                                                        
            }                                                                                    
            if(generateController) {
                event("StatusUpdate", ["Generating controller for domain class ${domainClass.fullName}"])    
                generator.generateController(domainClass,".")            
            }
            event("StatusUpdate", ["Finished generation for domain class ${domainClass.fullName}"])            
        }
        event("StatusFinal", ["Finished generation for domain classes"])
    }
    else {
        event("StatusFinal", ["No domain class found"])
    }
}


Then just run grails uber-generate-all and watch!

I have only tested it for Groovy domain classes, but I think it will also work for Hibernate mapped classes. Enjoy.

Sunday, May 4, 2008

Ref Code plugin



Back in my days as Oracle Designer developer we had a nice CG_REF_CODES table in which we could store (semi)-static domains. You can think about these domains as simple code/description lookup tables; for example OrderStatus, OrganizationType, MaritalState etc. As these lookups only contained codes and descriptions it's not worth creating specific tables. That's why we had this CG_REF_CODES tables; we stored all these simple domains, and it's allowable values in 1 simple table.

As this is convienient for any application I created a simple Grails plugin which provides the same functionality. You can store all your simple reference codes in a single table, and use it to render dropdown boxes or validate user input in custom constraints. Have a look at http://grails.org/Ref+Code+Plugin.