Table of Contents
|
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
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.