Grails

Ajax

Thanks to this link I've discovered the existence of 'g:remoteLink' and 'g:formRemote' which will avoid to manually implement a lot of javascript calls. Well, it is not possible to read all the documentation in one day!

Releasing with maven

Making a release of a grails app with maven.

Building Grails

I've found problems when building Grails in both linux and osx. After downloading the sources, I execute the ant command and get a test failure:

run-test:
   [delete] Deleting directory /home/oliver/prog/groovy/grails-1.0.4/target/test-reports
    [mkdir] Created dir: /home/oliver/prog/groovy/grails-1.0.4/target/test-reports
     [echo] Test being run * from target/test-classes
    [junit] TEST grails.build.eclipse.EclipseClasspathTests FAILED

then the building hangs but with a lot of processor activity. To solve this I've imported Grails as an Eclipse project, this creates the required '.classpath' file. Now the test checks the libraries and succeeds.

But I still have problems because on the 'prerequisites' section of 'Installation from Subversion' on the grails installation page it is said that the system requires a 1.6.5 or higher version of Ant but Grails sources are already bundled with the Ant library. Then when building an Ant conflict appears. What I've done is to remove my Ant installation from the PATH and use the GRAILS_HOME/ant/bin/ant command.

After this changes the build succeeds and I get the dist directory filled with the bins of the Grails 1.0.4 distribution.

Custom exception handling

http://blog.bruary.net/2008/03/grails-custom-exception-handling.html

Dependency injection

From http://grails.org/Advanced+Topics

Autowiring by name (default)

The default behaviour is injection by name. This convention is so because in dynamically typed languages we declare configuration properties without specifying its type:

/**
 * Dependencies are autowired by name.
 */
class MyConfigurableBean
{
    def requiredService
}

and as the only type we can be sure for 'requiredService' is 'java.lang.Object' the DI container will throw an error because all instances it manages are 'java.lang.Object' instances.
Thus, the autowiring by name is the standard way on Grails.

Autowiring by type

Anyway, autowiring by type can also be configured on each Controller by adding a 'byName' property setted to false.

/**
 * Dependencies are autowired by type.
 */
class MyConfigurableBean
{
    boolean byName= false
    BookingService bookingService
}

Avoiding a bean to be dependency injected

There will be cases when you will prefer to inject beans manually to avoid type conflicts and confusions.
For this cases you can disable autowiring on your beans by adding an 'available' property setted to false to them. For example:

/**
 * Autowiring is disabled. 'firstService' and 'secondService' should be manually injected.
 */
class MyConfigurableBean
{
    boolean available= false
    def firstService
    def secondService
 
}

Grails configuration properties

It should be notted that when there is a property of some type that should be configured by Grails on a bean it is allowed to have another property with the same name but another type. Thus this is legal:

/**
 * Grails will configure the bean using the 'boolean transactional' property, and will ignore 'String transactional'.
 */
clas MyConfigurableClass
{
    boolean transactional = false
    String transactional = "false" // this property is ignored for configurational purposes.
}

Anyway, is it usefull? I think it is a bad practice to have a property referring to different things named the same way.

Dynamic Methods

Based on Groovy's Meta Object Protocol Grails delivers its Dynamics Methods which are methods that does'nt exist on the code of the classes but that are available on classes at runtime. Those methods can be undertood as methods that are injected at class construction time. They are very poweful. For example, the description of the Grails Domain classes addTo* method says

Adds a domain class relationship for one-to-many or many-to-many relationship, where the relationship is indicated by the property used as the suffix to the method.

so one can call

receipt.addToIngredients(new Ingredinent(amount:250, units: 'gr', food:'rice'))

without having to implement any addToIngredients method nor having to extend Receipt from any class. The method is added at runtime.

TODO read this: http://grails.org/Dynamic+Methods+Reference

Filters

Searching for grails filter documentation I've arrived to this how to http://www.grails.org/Filters

Fixtures

The fixtures plugin allows you to easily define a graph of domain objects and save them to the database. You can use this to establish a data set to use while developing your app, or to define common data to use for your integration tests.
http://www.grails.org/Fixtures+Plugin

GORM

I can not use 'select' while using HQL on findAll. It seems that whatever the query is Gorm doesn't accept this clause. I have to investigate further.

After reading this article -> http://www.ibm.com/developerworks/java/library/j-grails02128/index.html I've found it too introductory and will keep searching.

I18n on Grails

I recomend everyone to read "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets" article before keeping on with i18n because they are closely related.

Take care of this very important configuration default: if no explicit bundle exists for the user's language grails defaults to the OS lang and only if there is no bundle for the former defaults to de default.properties bundle.
It seems a complication over configuration situation that I can't understand. And the most surprising is that the grails team won't fix it: http://jira.codehaus.org/browse/GRAILS-3871 , a red light for the grails team on this.
As a workaround:

import grails.util.GrailsUtil
 
import org.codehaus.groovy.grails.commons.GrailsApplication
 
import org.codehaus.groovy.grails.web.context.ServletContextHolder
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes
 
class BootStrap {
     def fixtureLoader
 
     def init = { servletContext ->
         // HACK: avoid default configuration of messageSource!!!
        def appContext = servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
        def messageSource = appContext.getBean("messageSource")
        messageSource.fallbackToSystemLocale = false
        ...
    }
}

If you want your scaffolding to be i18n aware take a look at: http://grails.org/I18n+Templates+Plugin

Grails i18n is based on Spring and Java bundles.
You should place your internationalized messages at '/grails-app/i18n', all i18n files must be encoded in UTF-8 because grails will translate all non ascii characters to escaped unicode (wich will save us a lot of work ;). They will be accessible on the context as 'context.messageSource', on the view you should use the 'g:message' tag instead.

You can use multiple bundles (not only the messages.properties), Grails will load all of them. Thus you can divide your i18n bundles for example by views, by domain entity, etc.

For more information about how Grails i18n works read: http://grails.org/Internationalization .

IDE integration

http://brainflush.wordpress.com/2008/05/03/grails-and-eclipse-not-so-groovy/

JSON

http://memo.feedlr.com/?p=6

Logging

To see the full stack trace of an Exception (which by default must be at) :

  • try grails.util.GrailsUtil.deepSanitize(throwable)
  • Look at your "stacktrace.log" file.
  • grails -Dgrails.full.stacktrace=true run-app

Security

Here is a little Grail's JSecurity Plugin HowTo: jsecurityPlugin.
And this is another one: http://asrijaffar.blogspot.com/2008/08/grails-jsecurity-plugin.html

Taglib use of encodig

I've been having problems in my team while testing our custom TagLibs. The case is that we're using Windows and Linux machines and when the TagLibs generate its result the new line encoding is different depending on which machine we're executing the tests. As we are using control files to compare the TagLib output with the expected output we find problems on Linux or Windows depending on who've created the control file.

Our solution has been to perform somthing like

tagLibResult= tagLibResult.replace("\\r\\n", "\\n")
expected= expected.replace("\\r\\n", "\\n")

Another solution may have been to use the same approach as in Grails' TagLib tests, use the 'assertContains' and check for expected parts on the output, which is less precise but may be ok and less maintainable.

Testcase UrlMappings

I'm having problems with the resolution of url mappings. Is the order important? i think no.
How it resolves /controller/id?/action? for this cases:
/app/controller/
/app/controller/action
/app/controller/id
/app/controller/id/action

I've found this interesting link http://www.grails.org/Testing+URL+Mappings which I have to read further.

Tutorials for Grails

http://www.grailstutorials.com

Wiring methods to classes

Extract from the grails user mailing list:
There's a new feature in the 1.1 branch that adds a 'withSession' static method to domain classes, like the 'withTransaction' method that's there now. It provides easy access to the current session for cases where you need functionality that Grails/GORM doesn't provide. You can wire this up in BootStrap.groovy now and remove it when you upgrade to 1.1:

  import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
  import org.springframework.orm.hibernate3.HibernateCallback
  import org.springframework.orm.hibernate3.HibernateTemplate

  class BootStrap {

     def sessionFactory

     def init = { servletContext ->
        AH.application.domainClasses.each { dc ->
           dc.metaClass.'static'.withSession = { Closure callable ->
              new HibernateTemplate(sessionFactory).execute({ session ->
                 callable(session)
              } as HibernateCallback)
           }
        }
     }

     def destroy = {}
  }

Then you can run this:
  MyPoint.withSession { session ->
     session.createQuery(...)
     ...
  }

Upgrading

Upgrading to grails 1.1-RC1 with maven.
Upgrading to grails 1.2 with maven.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License