Grails is a metaframework in that it ties together several other frameworks, and none is more pervasive in Grails than the Spring Framework. Grails uses a significant amount of Spring core functionality and optional modules including managing artifacts and many classes as Spring beans (using Springâs dependency injection to manage the graph of dependencies), its datastore integration features (by default using its Hibernate integration), support for proxies and AOP to enable transparent transactions (and caching and security via plugins), internationalization, resource management, and a lot more.
In addition, there are many Spring extensions (both official and third party) that are readily usable in a Grails application. Many are already exposed via plugins (e.g., Spring Security), but if not, you can use an extension like you would in any Spring-based application. You can use annotated bean classes or the newer Java configuration, or copy bean definitions into grails-app/conf/spring/resources.xml (this isnât created by default so you need to create it yourself) or convert them to Groovy syntax in resources.groovy. Register any dependencies in BuildConfig.groovy, and youâre ready to go.
One of the central ideas of Spring that Grails uses heavily is Inversion of Control (IoC), also known as Dependency Injection (DI). This reverses the direction of managing object dependencies from the older style of creating them directly or pulling them in from a repository (e.g., JNDI) to a style where beans donât know how to retrieve their dependencies, but have setter methods and constructors that are used to push dependencies in. This obviously changes everything and opens up many possibilities for much more dynamic and loosely coupled code, and fits the Grails model very well.
In older versions of Spring dependency injection, you would use XML configuration files, but now itâs as simple as using the @Autowired
annotation. In Grails, itâs even simpler; any Spring bean written in Groovy (this includes all of the standard artifacts such as controllers, services, and taglibs) can inject the userService
bean by adding the line:
def
userService
as a class-scope field. You can specify the type of the field if you want (this can help IDE autocompletion), but itâs not necessary.
This seems quite magical but, like most things in Grails (and Groovy), itâs actually very simple. It makes a lot more sense if you recall that fields in Groovy classes that donât have a scope modifier are, by default, public, and the Groovy compiler converts them to a private field and a getter and setter (unless you have already created the getter or setterâit wonât replace yours). This means that this field is actually implemented as if you had this code:
private
Object
userService
void
setUserService
(
Object
userService
)
{
this
.
userService
=
userService
}
Object
getUserService
()
{
return
userService
}
For our purposes, the getter isnât very useful, but the setter is. Thatâs because, by default, Grails creates its beans with autowiring enabled, and is set to âby nameâ mode. So, as Spring is building its ApplicationContext
and wiring together the various dependencies, if it sees a setter whose property name matches a bean name, it will call the setter to inject that bean. So, even though Spring doesnât know anything about Groovy, because it sees the public setter that the Groovy compiler created, it injects the userService
bean into your bean as if you had created the setter for that purpose.
Therefore, it should be clear why adding def beanName
inside a method doesnât work: itâs just a local variable and not a candidate for dependency injection.
In general, setting bean dependencies in resources.groovy is done with either other beans or properties that are numbers, strings, Booleans, etc. But you can use Spring Expression Language (SpEL) in property value strings to access other beansâ properties and even call their methods. For example, if the Bar
class has a name
property (or getName
method), you can access it to configure the foo
bean:
beans
=
{
bar
(
Bar
)
foo
(
Foo
)
{
name
=
'#
{
bar
.
name
}
'
}
}
Or, if you want to leave the logic for how to resolve the property in the Foo
class, you can call a method instead:
beans
=
{
bar
(
Bar
)
foo
(
Foo
)
{
name
=
'#
{
bar
.
resourceName
()}
'
}
}
For more information, see the relevant section in the Spring documentation, Expression support for defining bean definitions.
If you manually instantiate classes that arenât Spring beans, but would like to conveniently inject Spring bean dependencies into them (e.g., classes in src/groovy and src/java), you can do this if you have access to the Spring ApplicationContext
. This is simple if you dependency-inject the grailsApplication
bean into the artifact class (e.g., a controller or a service) that is creating the instance:
def
grailsApplication
and then you can autowire properties by name with this:
import
org.springframework.beans.factory.config.AutowireCapableBeanFactory
...
def
instance
=
new
XXX
(...)
def
ctx
=
grailsApplication
.
mainContext
ctx
.
beanFactory
.
autowireBeanProperties
(
instance
,
AutowireCapableBeanFactory
.
AUTOWIRE_BY_NAME
,
false
)
Just as in Spring bean classes or Grails artifact classes, any public property or setter method that corresponds to a bean name in the ApplicationContext
will be set with that bean.
By default, Spring beans are singletons: only one instance is created, and each time you get the bean from the ApplicationContext
(either directly or via dependency injection), youâll get the same instance. This is a sensible default, because beans often have no mutable state, so theyâre safe to share between collaborators and between threads. They can have state, in particular injected dependencies, but as long as this state is initialized early and not changed, itâs not a thread-safety concern. Spring manages creating the instances and wiring dependencies, but without the problems associated with traditional singletons. Of course there are plenty of reasons why a particular bean cannot be a singleton, so beans can have a âscope.â
To receive a new instance from the ApplicationContext
each time, set the scope of the bean to prototype
. It will still have dependencies injected like singleton beans, but now it can have mutable state, because each caller gets its own copy. Grails controllers are an example of prototype beans; this is to support a rarely used feature inspired by Rails controllers where the controller itself is used as the GSP model when none is specified. Often, when a GSP is used to render a response, the last statement of a controller action is a Map
containing the model data to use in the GSP; if you donât return anything (and donât call redirect
, forward
, or chain
), then the controllerâs fields are used as the model data.
Another supported scope is session
. You could use this for shopping carts and other similar patterns, much like a stateful EJB session bean. The first time the bean is requested from the ApplicationContext
, it is created and stored in the HTTP session, and subsequent requests return this instance until the session times out or is explicitly invalidated. Separate sessions each get their own instance. A similar scope is request
; these are created per request instead of per session, so theyâre much shorter lived.
You can also define your own scope by implementing the org.springframework.beans.factory.config.Scope
interface and registering it in the BeanFactory
:
ctx
.
beanFactory
.
registerScope
'
myScope
'
,
new
MyScope
()
You can use this in a controller or service class with the scope
property; for example:
static
scope
=
'
myScope
'
// or session/prototype/etc.
For Spring beans that you manually wire in resources.groovy, add the property in the bean definition:
myBean
(
MyBeanClass
)
{
bean
->
bean
.
scope
=
'
myScope
'
// or session/prototype/etc.
}
If you follow the convention for Grails services and create a Groovy class in the grails-app/services folder whose name ends in Service
, the class will automatically be registered as a service for you. This means that, by default, it is registered as a Spring bean (whose bean name is the class name with a lowercase first letter), the bean scope is singleton
, and all public methods will be transactional. That makes the class a great place to put business logic, especially if it involves database persistence.
You can specify the bean scope of a service with the static scope
property; this can be any valid value supported by Spring and the most common are singleton
and prototype
, and to a lesser extent request
and session
. The default scope (if none is specified) is singleton
.
By default, all public methods in a service are transactional. Older versions of Grails included the line static transactional = true
in generated services, but that has been removed, because itâs redundant. You should only set the transactional
attribute if youâre disabling transactionsâfor cases where the service manages business logic but doesnât write to the database.
The transaction isolation is set to Isolation.DEFAULT
; that is, the default settings for your database are used instead of explicitly using read-commited, serializable, etc. The propagation level is Propagation.REQUIRED
, which means that, if a transaction was already active before calling a service method, it will be joined and not committed after successfully invoking the method, because it was already started; however, if one isnât active, it will create one and commit it after invoking the method. There is no timeout configured, the transaction wonât be read-only, and the Exception
types that trigger an automatic rollback are the defaults; runtime exceptions and errors trigger rollback and checked exceptions (even though Groovy doesnât make you catch or rethrow checked exceptions) do not cause a rollback. This last point can be confusing for developers without much experience with Spring or JEE transactions. The logic is that in Java, because you must either catch a checked exception or declare it in the throws
clause, you have the opportunity to handle the exception and will decide if the exception merits an explicit rollback. But because you donât have to catch runtime exceptions or errors, itâs assumed that the transaction should be automatically rolled back for you, to keep state from being inconsistent. Because Spring doesnât know about Groovyâs exception handling rules, the Java rules apply.
Youâre not limited to the default transaction settings or forced to use complex configurations to customize servicesâ transaction behaviors. Customizing is simple; use the org.springframework.transaction.annotation.Transactional
annotation. If you have even one @Transactional
annotation, Grails assumes that youâre taking the configuration into your own hands and doesnât configure the default transaction settings for the class. You can put the annotation at the class level, and/or on individual methods, and you can combine class-scope and method-scope annotations to configure default settings at the class level, but configure overrides for individual methods.
In this example, someMethod
will be transactional, inheriting the settings from the class annotation, but someOtherMethod
requires that an existing transaction be active:
package
com
.
mycompany
import
org.springframework.transaction.annotation.Propagation
import
org.springframework.transaction.annotation.Transactional
@Transactional
class
SomeService
{
def
someMethod
()
{
...
}
@Transactional
(
propagation
=
Propagation
.
MANDATORY
)
def
someOtherMethod
()
{
...
}
}
Another approach is to omit the annotation at the class level to support nontransactional methods and to annotate methods directly. In this example, someMethod
is not transactional (but wonât trigger an exception if it is called during a transaction), someOtherMethod
has the default settings, and yetAnotherMethod
requires that a transaction be active already:
package
com
.
mycompany
import
org.springframework.transaction.annotation.Propagation
import
org.springframework.transaction.annotation.Transactional
class
SomeOtherService
{
def
someMethod
()
{
...
}
@Transactional
def
someOtherMethod
()
{
...
}
@Transactional
(
propagation
=
Propagation
.
MANDATORY
)
def
yetAnotherMethod
()
{
...
}
}
Whether you use the default Grails configuration or annotations, the transaction management is implemented by Spring with a proxy. Spring uses the CGLIB library to create a subclass of your service, where each proxied method (all public methods when not using annotations or if the class is annotated, annotated public methods otherwise) is intercepted by the proxy to start or join a transaction (or throw an exception if one isnât allowed) and then call your implementation code. You can see that this is the case by printing the class name of your injected service, (e.g., println userService.getClass().name
); it should look something like this:
com
.
foo
.
bar
.
UserService
$$EnhancerByCGLIB$$32cb6433
We can see that the proxy is a runtime-generated subclass of the real bean class by printing its superclass:
println
userService
.
getClass
().
superclass
.
name
which should print:
com
.
foo
.
bar
.
UserService
Digging further, we can list all of the interfaces implemented by the proxy:
for
(
iface
in
ctx
.
mathService
.
getClass
().
interfaces
)
{
println
iface
.
name
}
which should print:
org
.
springframework
.
aop
.
SpringProxy
org
.
springframework
.
aop
.
framework
.
Advised
net
.
sf
.
cglib
.
proxy
.
Factory
Be careful when calling annotated methods within a service when the annotation settings are different. Because youâre âunderneathâ the proxy, itâs a direct method call, and any checks that the proxy would have done will be bypassed. For example, if you want to store auditing data in the database, but donât want a failure there to roll back the transaction, you can do that work in a new transaction by setting the propagation to Propagation.REQUIRES_NEW
:
@Transactional
void
someMethod
(...)
{
// do some work ...
storeAuditData
(...)
}
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
void
storeAuditData
(...)
{
//
}
Unfortunately, though, the call to storeAuditData
wonât trigger the creation of a second transaction, because itâs a direct call. You can fix this by calling the proxyâs method, and that involves getting access to the Spring bean that represents this service. You canât just add a dependency injection (def fooService
), because that would be circular; instead, if you add a dependency injection for the grailsApplication
bean, you can access the ApplicationContext
easily from there and get the service from it:
def
grailsApplication
@Transactional
void
someMethod
(...)
{
// do some work ...
def
myProxy
=
grailsApplication
.
mainContext
.
fooService
myProxy
.
storeAuditData
(...)
}
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
void
storeAuditData
(...)
{
//
}
Another more traditional option is to implement the org.springframework.context.ApplicationContextAware
interface, but that involves more plumbing code.
An even more automatic fix would be to wire up a getMyProxy()
method (and therefore a myProxy
property) into the metaclass of all services in BootStrap.groovy:
class
BootStrap
{
def
grailsApplication
def
init
=
{
servletContext
->
for
(
sc
in
grailsApplication
.
serviceClasses
)
{
sc
.
clazz
.
metaClass
.
getMyProxy
=
{
->
grailsApplication
.
mainContext
.
getBean
(
sc
.
propertyName
)
}
}
}
}
or in the doWithDynamicMethods
callback in a plugin:
def
doWithDynamicMethods
=
{
ctx
->
for
(
sc
in
application
.
serviceClasses
)
{
sc
.
clazz
.
metaClass
.
getMyProxy
=
{
->
application
.
mainContext
.
getBean
(
sc
.
propertyName
)
}
}
}
and then this call would have the expected effect:
@Transactional
void
someMethod
(...)
{
// do some work ...
myProxy
.
storeAuditData
(...)
}
@Transactional
(
propagation
=
Propagation
.
REQUIRES_NEW
)
void
storeAuditData
(...)
{
//
}
For complex workflows, it can be helpful to have access to information about the current transaction. Ironically, although services are the best place in Grails to do transactional work, the static withTransaction
method thatâs available in all domain classes is more useful in this regard, because the method signature has an org.springframework.transaction.TransactionStatus
variable. But thereâs no direct way to access information about the current transaction in a service. Thatâs easy to fix thoughâwe can add some transaction utility methods to service metaclasses; for example, in BootStrap.groovy:
import
org.springframework.transaction.interceptor.TransactionAspectSupport
import
org.springframework.transaction.support.TransactionSynchronizationManager
class
BootStrap
{
def
grailsApplication
def
init
=
{
servletContext
->
for
(
sc
in
grailsApplication
.
serviceClasses
)
{
def
metaClass
=
sc
.
clazz
.
metaClass
// returns boolean
metaClass
.
isTransactionActive
=
{
->
TransactionSynchronizationManager
.
isSynchronizationActive
()
}
// returns TransactionStatus
metaClass
.
getCurrentTransactionStatus
=
{
->
if
(!
delegate
.
isTransactionActive
())
{
return
null
}
TransactionAspectSupport
.
currentTransactionStatus
()
}
// void, throws NoTransactionException
metaClass
.
setRollbackOnly
=
{
->
TransactionAspectSupport
.
currentTransactionStatus
().
setRollbackOnly
()
}
// returns boolean
metaClass
.
isRollbackOnly
=
{
->
if
(!
delegate
.
isTransactionActive
())
{
return
false
}
delegate
.
getCurrentTransactionStatus
().
isRollbackOnly
()
}
}
}
}
Now you can force the transaction to roll back by calling setRollbackOnly()
and, in a workflow that has multiple steps, you can call isRollbackOnly()
early in each method before doing expensive work that will only be rolled back, to see if that work makes sense to do.
In addition to wiring up dependencies between beans, the ApplicationContext
is responsible for managing the beansâ life cycles. Two important hooks are the initialization and destruction phases. When you register your own Spring beans in resources.groovy, you can use the org.codehaus.groovy.grails.commons.spring.BeanConfiguration
instance (typically a org.codehaus.groovy.grails.commons.spring.DefaultBeanConfiguration
) that is the argument of the bean definition closure to set the initMethod
and/or the destroyMethod
names; for example:
authenticationManager
(
com
.
mycompany
.
myapp
.
LdapAuthenticationManager
)
{
bean
->
serverUrl
=
'
...
'
password
=
'
...
'
bean
.
initMethod
=
'
init
'
bean
.
destroyMethod
=
'
destroy
'
}
Most of the time, however, the beans that you create are automatically registered for you by Grails. In that case, you can implement the org.springframework.beans.factory.InitializingBean
interface and its afterPropertiesSet
method to do initialization work after all dependencies and other properties have been set, and the org.springframework.beans.factory.DisposableBean
interface and its destroy
method to do work during a clean shutdown; for example:
package
com
.
mycompany
.
myapp
import
org.springframework.beans.factory.DisposableBean
import
org.springframework.beans.factory.InitializingBean
class
LdapAuthenticationManager
implements
InitializingBean
,
DisposableBean
{
...
void
afterPropertiesSet
()
{
// initialization work
}
void
destroy
()
{
// shutdown work
}
}
Note
Whether you use initMethod
or InitializingBean.afterPropertiesSet
, because Spring is unaware of the various Grails life cycle phases, you are somewhat limited in what you can do in the initialization phases. In particular, because plugins wonât have initialized yet, you cannot use GORM methods. If you find you cannot do some initialization work because of this, you can inject your bean in BootStrap.groovy and do the work there, because by the time bootstrap classes are called, everything has been configured and is ready to use.
In earlier versions of Grails, the log
field was added using runtime metaprogramming, but in Grails 2.0 and higher, itâs injected with an AST transformation (compile-time metaprogramming), so you can use logging in either callback method.
Bean (and BeanFactory
and BeanDefinitionRegistry
) postprocessors provide a powerful approach to customizing Spring beans. Theyâre particularly useful to reconfigure beans contributed by third-party JARs or plugins where you canât (or shouldnât) edit the code. Instead, you can hook into the construction process and customize one or more beans at runtime, changing or adding properties, the bean implementation class, and other attributes and settings.
The most common interface to use is org.springframework.beans.factory.config.BeanPostProcessor
, which has two methods, postProcessBeforeInitialization
and postProcessAfterInitialization
. You can do what you want with each, but typically postProcessBeforeInitialization
works with class metadata like annotations, because the instance has been created but it isnât fully initialized yet. Itâs common to return a proxy for the real instance from postProcessAfterInitialization
, although you can also just reconfigure the initialized instance with updated properties.
You can also create an org.springframework.beans.factory.config.BeanFactoryPostProcessor
, which has one method, postProcessBeanFactory
. This takes a single argument: a ConfigurableListableBeanFactory
that you can use to customize a BeanDefinition
from its getBeanDefinition
method, or loop through all of the beans using the names from the getBeanDefinitionNames
method. Your postprocessor will be called after the bean factory is partially initialized but before beans have been instantiated. This gives you a chance to modify the BeanDefinition
instances that will be used to define the actual beans. You can add, remove, or change bean properties and even the class that will be instantiated.
The org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
interface extends BeanFactoryPostProcessor
and has one method, postProcessBeanDefinitionRegistry
, where you can add or remove BeanDefinition
instances in the BeanDefinitionRegistry
.
To add a postprocessor, implement whichever interface(s) you want in a class in src/groovy or src/java and register it as a bean (using any name you want, because itâs not particularly relevant) in resources.groovy. Spring will see that it implements one of the interfaces and will use it as a postprocessor, calling the methods at the appropriate points in the construction of the ApplicationContext
:
import
com.mycompany.myapp.MyPostProcessor
beans
=
{
myPostProcessor
(
MyPostProcessor
)
}
Note
The cloud-foundry
and heroku
plugins both provide runtime reconfiguration of the JDBC DataSource
, NoSQL connection information, and so on, using this approach. This keeps your application highly decoupled from the hosting location, because a bean postprocessor detects the environment variables that Cloud Foundry and Heroku make available, and transparently reconfigures the appropriate Spring beans for you. You can see the source of the shared base class that each plugin extends to provide provider-specific settings discovery here.
You can also customize a BeanDefinition
in the doWithSpring
closure in a plugin. The delegate
of the closure is the active grails.spring.BeanBuilder
that Grails uses to register beans in the ApplicationContext
that are defined by the builderâs DSL. You can use the getBeanDefinition
method to retrieve a previously defined bean definition (typically an org.springframework.beans.factory.support.GenericBeanDefinition
) and modify its attributes:
def
doWithSpring
=
{
def
beanDef
=
getBeanDefinition
(
'
someBeanName
'
)
beanDef
.
beanClass
=
NewClass
beanDef
.
propertyValues
.
add
(
'
order
'
,
application
.
config
.
plugin
?.
rendering
?.
order
?:
[])
}
Note that because this runs during your pluginâs initialization, plugin loading order is important; the only bean definitions that will be available are those configured by plugins that have already initialized. You can use the loadAfter
plugin descriptor attribute to configure this.
Spring allows bean aliases where an alternate name is registered in addition to the real name of a bean. You can use this when you have multiple implementations of a bean and choose one via configuration at startupâfor example, per-environment or some other rule. This is partially broken in Grails before 2.1 in that, before version 2.1, you could register aliases but only to beans in the same plugin or resources.groovy. As of version 2.1 though, all aliases work regardless of the location of the alias and bean definitions.
This works the same way in a pluginâs doWithSpring
as in resources.groovy, because in both cases, the closureâs delegate is the BeanBuilder
. You can access the RuntimeSpringConfiguration
with the getSpringConfig
method and call addAlias
on that; for example:
import
grails.util.Environment
beans
=
{
String
realBeanName
switch
(
Environment
.
current
)
{
case
Environment
.
TEST
:
realBeanName
=
'
testCardProcessingService
'
break
case
Environment
.
PRODUCTION
:
realBeanName
=
'
productionCardProcessingService
'
break
default
:
// Environment.DEVELOPMENT, custom envs
realBeanName
=
'
mockCardProcessingService
'
break
}
springConfig
.
addAlias
'
cardProcessingService
'
,
realBeanName
}
Now, when a controller or other artifact that supports dependency injection injects the cardProcessingService
bean, it will get the correct one depending on the current running environment. This has the benefit of centralizing the logic and not polluting the application code with logic to determine in each case which bean to use.
Note
The cache
plugin registers the alias cacheOperationSource
for the bean that Spring autoregisters as org.springframework.cache.annotation.AnnotationCacheOperationSource#0
, which cannot be used with Grails dependency injection using the standard def beanName
pattern.
Grails has first-class support for internationalization with the .properties files in the grails-app/i18n folder. All generated controllers, GSPs, and layouts are fully internationalized with no hardcoded strings; instead, strings are resolved from the message bundles defined in the .properties files using the message
tag and the current Locale
. In addition, domain class validation errors are internationalized the same way, using the i18n message bundles. This can make the code harder to read (especially if the message codes are cryptic or not intuitive), but it makes displaying your site in another language much simpler, because you just need to ensure that all English messages have corresponding translated messages for your supported languages.
This is all enabled under the hood by the use of the messageSource
bean, an implementation of the org.springframework.context.MessageSource
interface. In a Grails application, this will be a PluginAwareResourceBundleMessageSource
that supports loading messages from the application as well as from installed plugins and supports reloading in the development environment. You can work directly with the messageSource
bean using dependency injection like with any Spring bean: def messageSource
. Often itâs easier to use the message
tag because tags can conveniently be called in controllers. But, in services or other classes, where itâs impractical to call a taglib, just use the messageSource
bean.
Spring has an abstraction for low-level resources with its org.springframework.core.io.Resource
and org.springframework.core.io.ResourceLoader
interfaces. There are several concrete Resource
implementations, including UrlResource
, ClassPathResource
, FileSystemResource
, ServletContextResource
, InputStreamResource
, and ByteArrayResource
. It rarely matters what the concrete class is though, because you can use the methods exists()
, getInputStream()
, getURL()
, and so on.
For example, consider a configuration file that you put in the web-app/WEB-INF folder, data.xml. This is safe from public viewing, because the container blocks access to all files in WEB-INF. So how do you read the contents of the file at runtime? A naive approach that works in development mode is:
new
File
(
'
web
-
app
/
WEB
-
INF
/
data
.
xml
'
).
text
This wonât work in a deployed WAR for two reasons. One is that there is no web-app folder, and the other is that the WAR may not be expanded onto the filesystem depending on which container you use, so there may be no File
access at all even if you âfixâ the path. But you certainly wouldnât want to have brittle logic that computes the file path depending on how the application is running.
This method in ResourceLoader
looks promising:
Resource
getResource
(
String
location
);
So how do we access a ResourceLoader
in Grails? The ApplicationContext
implements the interface and will usually be the most convenient way to manage resources. Getting access to the ApplicationContext
can be done a few different ways; the most convenient is to add a dependency injection for the grailsApplication
bean (def grailsApplication
) because grailsApplication.mainContext
resolves to the ApplicationContext
; you can also implement ApplicationContextAware
.
Then itâs as simple as executing:
String
xml
=
ctx
.
getResource
(
'
WEB
-
INF
/
data
.
xml
'
).
inputStream
.
text
and thereâs no dependence on any particular environment or logic to compute various paths to the file, depending on how the application is being run, because Spring abstracts that away. If you run:
println
ctx
.
getResource
(
'
WEB
-
INF
/
data
.
xml
'
).
getClass
().
name
youâll see that the implementation class is org.springframework.web.context.support.ServletContextResource
, and running:
ctx
.
getResource
(
'
WEB
-
INF
/
data
.
xml
'
).
file
.
path
will print something like:
/
path
/
to
/
appname
/
web
-
app
/
WEB
-
INF
/
data
.
xml
when running under run-app
and:
/
usr
/
local
/
apache
-
tomcat
-
7.0
.
29
/
webapps
/
appname
/
WEB
-
INF
/
data
.
xml
when running as a WAR deployed to Tomcat (assuming Tomcat is configured to explode WARs).
A more automatic approach would be to use dependency injection to let Spring inject the resource into one of your beans, rather than explicitly pulling it like we have been. If you move the file from the WEB-INF folder to either grails-app/conf or src/java, it will be copied into the classpath, so we can access it as a classpath resource. Consider this simple class:
package
com
.
mycompany
.
myapp
import
org.springframework.core.io.Resource
class
FooManager
{
Resource
xmlFile
// class methods
}
If we wire this class up as a bean in resources.groovy, for example:
import
com.mycompany.myapp.FooManager
beans
=
{
fooManager
(
FooManager
)
{
xmlFile
=
'
classpath:
data
.
xml
'
}
}
then the resource will be discovered and injected into the bean. Now it will be an instance of org.springframework.core.io.ClassPathResource
, and accessing the content of the file is as simple as:
String
xml
=
xmlFile
.
inputStream
.
text
inside any of the methods in FooManager
. You can even go further and specify the type as a File
:
package
com
.
mycompany
.
myapp
class
FooManager
{
File
xmlFile
// class methods
}
and then the content will be available as:
String
xml
=
xmlFile
.
text
As of Grails 2.0, there is also another option for finding resources: the org.codehaus.groovy.grails.core.io.ResourceLocator
interface and its implementations. This has two primary methods: Resource findResourceForURI(String uri)
and Resource findResourceForClassName(String className)
. The advantage of using ResourceLocator
over the Spring option is that ResourceLocator
implementations are Grails classes and are aware of the structure of application and plugin paths and can also access contents of binary plugins.
To use this, get a reference to the grailsResourceLocator
bean, typically using dependency injection (e.g., def grailsResourceLocator
). Then you can conveniently access files when running locally using run-app
or when deployed as a WAR (e.g., getting the content of a JavaScript file provided by the JQuery plugin, without having to know anything about where the actual file is located):
def
resource
=
grailsResourceLocator
.
findResourceForURI
(
'
js
/
jquery
/
jquery
-
1.8
.
3
.
min
.
js
'
)
String
jqueryJs
=
resource
.
inputStream
.
text
or an application file you have placed in the WEB-INF folder:
def
resource
=
grailsResourceLocator
.
findResourceForURI
(
'
WEB
-
INF
/
someDataFile
.
xml
'
)
Data binding and validation help make integrating HTTP request data with domain classes much easier in Grails. Much of the core implementation is handled by Spring, with Grails adding a layer on top to make the integration more direct and add in special handling.
Spring provides several implementations of JavaBean PropertyEditor
s to convert String
s (typically from web requests) to numbers, dates, or anything that has a string form that can be converted. These are used by the org.codehaus.groovy.grails.web.binding.GrailsDataBinder
, which extends the underlying Spring data binding implementation to add Grails-specific hooks, such as working with the params
map in controllers, being aware of the constraints
property in domain classes, and guarding against changing properties such as metaClass
, id
, and version
.
Spring and Grails register several property editors, and you can register your own by registering a CustomEditorConfigurer
bean (a bean postprocessor), giving it a list of PropertyEditorRegistrar
instances referencing your editors. This is somewhat cumbersome though, but in Grails 2.3 the data binding implementation will be heavily refactored to retain the binding features, but add several new ones and significantly simplify the process for adding custom binding approaches.
In traditional Spring applications, it is common to create validators for the appâs DAOs, and Spring has an org.springframework.validation.Validator
interface to standardize the behavior. But there are no concrete implementations of the interface, because validation is very domain-specific. Although youâre probably unaware of it, Grails creates an instance of Validator
for each domain class; if you loop through the ApplicationContext
beans, youâll see that for a com.foo.bar.Person
domain class there will be a com.foo.bar.PersonValidator
bean (an instance of org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator
, if youâre using Hibernate) along with a com.foo.bar.Person
bean (a âprototypeâ bean that is used in the overridden constructor to create instances and support bean autowiring), a com.foo.bar.PersonPersistentClass
bean, and a com.foo.bar.PersonDomainClass
bean.
Validation problems are represented by the org.springframework.validation.Errors
interface, typically a grails.validation.ValidationErrors
instance, which extends a Spring implementation that provides most of the functionality. An Errors
instance is wired into all domain classes as the errors
property, making it very convenient to access after performing validation checks (either directly with the validate
method or indirectly with the save
method). It will contain information about what went wrong, including the original invalid values and error codes for displayable messages. This gets coupled with the Spring and Grails support for i18n message bundles (under the grails-app/i18n directory) to allow you to display human-readable validation messages and also support localized versions as needed.
Typically, we use GORM and Hibernate to manage database persistence in a Grails application, although many apps now use NoSQL datastores in addition to or instead of relational databases. Under the hood, the Hibernate integration is managed by Spring, from the org.springframework.orm.hibernate3.LocalSessionFactoryBean
factory bean (in Grails, itâs the org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean
subclass) thatâs used to configure org.hibernate.SessionFactory
instances to the org.springframework.orm.hibernate3.HibernateTransactionManager
implementation of the org.springframework.transaction.PlatformTransactionManager
interface that abstracts away the implementation details of transaction management (this is also a Grails-specific subclass, org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager
).
One significant feature of the Spring/Hibernate integration is the seamless access of active persistence objects. It would be cumbersome to explicitly open a Hibernate Session
or start a transaction and have to pass one or more related objects from method to method, so Spring stores various objects (the active transaction, the current Hibernate session, and so on) in ThreadLocal
scope, because web requests are handled per thread. So itâs easy for code thatâs aware of this pattern to access the current transaction or Hibernate session (or just know if one is active) by using the org.springframework.transaction.support.TransactionSynchronizationManager
and org.springframework.orm.hibernate3.SessionFactoryUtils
helper classes.
This is further helped by the org.codehaus.groovy.grails.orm.hibernate.support.GrailsOpenSessionInViewInterceptor
instance, which implements the org.springframework.web.context.request.WebRequestInterceptor
interface that Grails registers to intercept all controller requests. This interface has callbacks for doing work before a controller action starts, after it does its work, and after the view is rendered. This should sound familiar if youâve used filters before, because they are also managed by a WebRequestInterceptor
. The GrailsOpenSessionInViewInterceptor
opens a Session
at the start of all controller requests and registers it in thread-local scope (in an org.springframework.orm.hibernate3.SessionHolder
keyed by the owning SessionFactory
). Then, after the request, it flushes and closes the Session
.
So, for the entire duration of the request, there is always an active Session
available. This is important for a few reasons. The Hibernate implementation of GORM uses an org.springframework.orm.hibernate3.HibernateTemplate
under the hood to execute most queries. Criteria queries are relatively thin wrappers around the Hibernate Criteria feature, and where
queries, dynamic finders, and other GORM methods are converted to Criteria queries or call an applicable Hibernate Session
method. HibernateTemplate
uses SessionFactoryUtils.getSession()
to find or create a Session
. If one is active, it uses it and doesnât close it, because thatâs the responsibility of whatever code opened it (most likely, GrailsOpenSessionInViewInterceptor
). If one isnât, it creates one and closes it when finished. This is why lazy-loaded collections and entities fail to load when a query executes in a new thread; the instances retrieved become disconnected when the session closes. But, when the query runs in the requestâs
thread, the session is still active after the query, so lazy loading works. The plugins that enable asynchronous processing (Quartz, GPars, and Executor) all implement patterns similar to OpenSessionInView
, because they support running in new threads.
It is usually most convenient to use groovy.sql.Sql
when executing SQL queries in Groovy, but Spring has a utility class with many of the same features, JdbcTemplate
. You give it a reference to a DataSource
(typically, in the constructor) and it handles most of the gory details of getting a Connection
, Statement
, and ResultSet
for you (and closing them when it is finished), and has smart error handling which converts checked SQLExceptions
into a rich hierarchy of unchecked exceptions. The code ends up being a bit more verbose than using groovy.sql.Sql
but far more compact than the equivalent direct JDBC code:
import
misc.Person
import
org.springframework.jdbc.core.RowMapper
import
org.springframework.jdbc.core.JdbcTemplate
import
java.sql.ResultSet
import
java.sql.SQLException
def
dataSource
=
ctx
.
dataSource
def
template
=
new
JdbcTemplate
(
dataSource
)
long
id
=
...
Person
person
=
template
.
queryForObject
(
"select first_name, initial, last_name from person where id = ?"
,
[
id
]
as
Object
[],
new
RowMapper
<
Person
>()
{
Person
mapRow
(
ResultSet
rs
,
int
rowNum
)
throws
SQLException
{
def
p
=
new
Person
(
firstName:
rs
.
getString
(
'
first_name
'
),
initial:
rs
.
getString
(
'
initial
'
),
lastName:
rs
.
getString
(
'
last_name
'
))
p
.
id
=
id
p
}
}
)
Although theyâre less often used (especially in Grails), Spring does have support for JDO with the org.springframework.orm.jdo.JdoTemplate
and org.springframework.orm.jdo.support.JdoDaoSupport
classes, JPA with the org.springframework.orm.jpa.JpaTemplate
and org.springframework.orm.jpa.support.JpaDaoSupport
classes, and iBATIS (2.x) SQL Map
s.
Nearly all Grails applications have a web frontend, and most of the time, this is implemented with controllers. These are core artifacts in the grails-app/controllers folder. There are several convenient conventions associated with controllers; classes in the controllers folder are automatically registered as controllers, public closures and methods are automatically registered as actions, simply returning a Map
from an action renders the GSP corresponding to that controller and that action, using the Map
as the data model in the view, and the "/$controller/$action?/$id?" { ... }
URL mapping entry (added by default in the generated UrlMappings.groovy file) ensures that actions are automatically available externally using a REST-like URL scheme.
Your classes in grails-app/controllers donât implement the Spring Controller
interface (directly or via something funky like an AST transformation) and donât extend a Controller
base class; instead, Grails uses one facade Controller
to handle all requests: org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController
. This is registered as the mainSimpleController
bean. This delegates most of the work to the grailsControllerHelper
bean, an instance of MixedGrailsControllerHelper
which finds the action method or closure and invokes it, returning an org.springframework.web.servlet.ModelAndView
that you may be familiar with if youâve worked with Spring MVC in a traditional Spring application.
In addition, Grails invokes interceptors before and after controller actions. These come from various sources, including explicitly created HandlerInterceptor
classes such as GrailsOpenSessionInViewInterceptor
(via an org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter
adapter) and org.codehaus.groovy.grails.web.i18n.ParamsAwareLocaleChangeInterceptor
(which extends Springâs org.springframework.web.servlet.i18n.LocaleChangeInterceptor
), but also Grails filters and controller interceptors (beforeInterceptor
and afterInterceptor
closures defined in controller classes).
Filters in Grails are somewhat misleadingly named, because it seems like theyâre Servlet filters, but theyâre implemented with a HandlerInterceptor
(indirectly), so they only work with controller requests. For each filter class, Grails creates an adapter instance of org.codehaus.groovy.grails.plugins.web.filters.FilterToHandlerAdapter
to integrate it into the filters list. FilterToHandlerAdapter
implements the HandlerInterceptor
interface and extracts information from the DSL that developers use to define the filtering rules in an XXXFilters.groovy file (the patterns for which URIs, controllers, and actions apply; the before
, after
, and afterView
closures; and so on) to use when the various interface methods are called. This way, we can take advantage of the filter conventions so thereâs less plumbing work involved while still taking advantage of the Spring integration.
Controller interceptors look a lot like filters (although there are only the before and after phases, no âafter viewâ) but theyâre not implemented with a HandlerInterceptor
. Because they only apply to the controller where theyâre defined, the logic is applied per request, in AbstractGrailsControllerHelper
.
Note
If you need to intercept more than just controller requests, you can create a class that implements javax.servlet.Filter
(or extend an existing base class like org.springframework.web.filter.OncePerRequestFilter
) and add it to web.xml like in any application. This can be done in plugins in the doWithWebDescriptor
block, or in an application by running the install-templates
script and editing src/templates/war/web.xml.
Itâs been possible to use Spring MVC controllers in Grails since version 1.2; before that, it was possible with the springmvc
plugin. The process is fairly straightforward; create your controller classes in the src/java or src/groovy folder and add an org.springframework.stereotype.Controller
annotation. Grails doesnât autodiscover the annotated classes though; you need to add the relevant packages to the grails.spring.bean.packages
list property in Config.groovy; for example:
grails
.
spring
.
bean
.
packages
=
[
'
com
.
mycompany
.
myapp
.
billing
'
,
'
com
.
mycompany
.
myapp
.
card
.
api
'
]
When you create the classes, use the same techniques that you would in a traditional Spring application; for example, annotating an action method with org.springframework.web.bind.annotation.RequestMapping
:
@RequestMapping
(
"/mvc/hello.dispatch"
)
public
ModelMap
handleRequest
()
{
return
new
ModelMap
()
.
addAttribute
(
"text"
,
"some text"
)
.
addAttribute
(
"cost"
,
42
)
.
addAttribute
(
"config"
,
grailsApplication
.
getConfig
().
flatten
()));
}
One unfortunate aspect of the integration is that all RequestMapping
URI values must end in .dispatch
. You can make this more natural by adding entries in UrlMappings.groovy; for example:
class
UrlMappings
{
static
mappings
=
{
...
"/mvc/hello"
(
uri:
"/mvc/hello.dispatch"
)
"/mvc/other"
(
uri:
"/mvc/other.dispatch"
)
}
}
These controller classes will become standard Spring beans, so theyâre candidates for dependency injection. Use the org.springframework.beans.factory.annotation.Autowired
annotation on fields in Groovy classes:
@Autowired
def
grailsApplication
and on setters in Java:
private
GrailsApplication
grailsApplication
;
@Autowired
public
void
setGrailsApplication
(
GrailsApplication
app
)
{
grailsApplication
=
app
;
}
You can also use the javax.inject.Inject
annotation; for example, using constructor injection:
private
GrailsApplication
grailsApplication
;
@Inject
public
FooController
(
GrailsApplication
app
)
{
grailsApplication
=
app
;
}
Spring has support for remoting using several protocols. The Grails remoting
plugin implements this support for remote method invocation (RMI), Hessian (Cauchoâs lightweight binary HTTP-based protocol), Burlap (another protocol from Caucho, which uses XML), and Springâs HTTP invoker (implemented by Java serialization via HTTP).
The plugin makes it simple to provide remote access to a Grails service. The service must implement an interface, because it will be used to create a proxy that clients use to make the remote calls. For example, consider this simple interface (in this case, a Groovy version in src/groovy, but it can also be written in Java or from a JAR file):
package
test
.
remoting
interface
Math
{
int
add
(
int
i1
,
int
i2
)
int
multiply
(
int
i1
,
int
i2
)
}
Creating the remoted service only requires two things: you have to implement the interface, and you have to add a static expose
property containing a list of one or more protocol names to expose (any of burlap
, hessian
, httpinvoker
, and rmi
). This service (in grails-app/services like any Grails service) exposes all four protocols:
package
test
import
test.remoting.Math
class
MathService
implements
Math
{
static
expose
=
[
'
hessian
'
,
'
rmi
'
,
'
httpinvoker
'
,
'
burlap
'
]
int
add
(
int
i1
,
int
i2
)
{
i1
+
i2
}
int
multiply
(
int
i1
,
int
i2
)
{
i1
*
i2
}
}
The plugin adds a servlet (an org.springframework.web.servlet.DispatcherServlet
) for each protocol and an org.springframework.web.servlet.HandlerMapping
to route to them, and registers a proxy (using an org.springframework.aop.framework.ProxyFactoryBean
and an org.springframework.aop.target.HotSwappableTargetSource
) in the ApplicationContext
for each remoted service (in this example, MathServiceProxy
and MathServiceTargetSource
beans). In addition, for each exposed protocol, it registers an org.springframework.remoting.support.RemoteExporter
subclass (e.g., an org.springframework.remoting.caucho.HessianServiceExporter
for the Hessian protocol) bean (in this example, burlap.MathService
, hessian.MathService
, httpinvoker.MathService
, and rmi.MathService)
.
The most convenient way for clients to connect to your exposed services is to use Springâs client support for the various protocols, and Grails applications using the remoting plugin can create services that connect to remoted services just as easily as exporting the remoted services in the server application. All thatâs involved is creating a service with the same name as the remoted service (the package can be different) and adding a remote
property defining connection information.
The service shouldnât implement the interface that the remote service exposes, but it must be available in the classpath; it would be a good idea to create a third Java/Groovy project containing all of your remoted interfaces and any custom classes used in method calls and adding the generated JAR file to the dependencies of the server and client applications. This is because the plugin just uses the service as a container for the remote
property and replaces it in the ApplicationContext
with a proxy (an org.springframework.remoting.support.RemoteAccessor
subclass such as an org.springframework.remoting.caucho.BurlapProxyFactoryBean
for the Burlap protocol) bean that does implement the interface and makes the remote calls for you.
The remote
property is a Map
and specifies the interface to implement (under the iface
key) and the remote protocol to use (under the protocol
key); the protocol value can be one of the four supported values that are valid in the expose
list in the remoted service class. In addition, you must specify the connection information. If you specify the full URL string under the url
key it will be used; otherwise, the host
, port
, and webcontext
values are used to build a URL. host
defaults to localhost
if not specified, âportâ defaults to 1199 when using RMI or 8080 otherwise, and webcontext
defaults to the root context.
For example, this service will create a proxy client using Hessian:
package
client
class
MathService
{
static
remote
=
[
protocol:
'
hessian
'
,
iface:
test
.
remoting
.
Math
,
host:
'
my
.
server
.
com
'
,
port:
8888
,
webcontext:
'
remote
'
]
}
This service will create a proxy client using Burlap:
package
client
class
MathService
{
static
remote
=
[
protocol:
'
burlap
'
,
iface:
test
.
remoting
.
Math
,
host:
'
my
.
server
.
com
'
,
port:
8888
,
webcontext:
'
remote
'
]
}
This service will create a proxy client using HttpInvoker:
package
client
class
MathService
{
static
remote
=
[
protocol:
'
httpinvoker
'
,
iface:
test
.
remoting
.
Math
,
host:
'
my
.
server
.
com
'
,
port:
8888
,
webcontext:
'
remote
'
]
}
Finally, this service will create a proxy client using RMI:
package
client
class
MathService
{
static
remote
=
[
protocol:
'
rmi
'
,
iface:
test
.
remoting
.
Math
,
host:
'
my
.
server
.
com
'
,
port:
10199
,
webcontext:
'
remote
'
]
}
Using the Java Message Service (JMS) is a common way to add synchronous and asynchronous messaging to an application, to make the application components more loosely coupled and reliable. Spring adds support for sending and receiving messages by using JMS topics and queues. It is common to use the org.springframework.jms.core.JmsTemplate
helper class, which has features similar to the JdbcTemplate
JDBC helper. It manages connecting to the JMS ConnectionFactory
, provides helper methods to abstract away the rather cumbersome JMS API, and also converts checked JMSException
s to a hierarchy of runtime exceptions.
Enterprise JavaBeans (EJBs) are rarely used in Grails applications, because Spring and Grails provide lightweight replacements for most of the useful features of EJB; for example, Hibernate and GORM (and now NoSQL support) instead of Entity beans, Grails services instead of stateless and stateful session beans, and the jms
plugin to use JMS instead of message-driven beans. But, if you have existing EJBs that provide useful services, thereâs no need to rewrite them unless you also need the benefits of deploying on a lightweight container instead of a full application server, and Spring has several integration hooks to make EJB access transparent to your code.
There are plenty of highend monitoring solutions for web applications, but JMX remains as a simple and straightforward solution for monitoring and configuring aspects of an application using tools like JConsole (which is included with all JDK installs). Spring offers integration with JMX through various helper classes such as org.springframework.jmx.export.MBeanExporter
and others.
It shouldnât be much of a surprise that thereâs a Grails plugin to make using JMX even easier: the jmx
plugin significantly reduces the amount of configuration you need to do.
It creates a javax.management.MBeanServer
by using the Spring org.springframework.jmx.support.MBeanServerFactoryBean
factory bean, and automatically registers a Log4j and an org.hibernate.jmx.StatisticsService
MBean (the latter only if the Hibernate plugin is installed). In addition, it exposes any Grails service that declares static expose = ['jmx']
and any Spring beans listed in the grails.jmx.exportBeans
attribute in Config.groovy as MBeans. All public setters and getters are exposed except for any that you exclude using the pluginâs configuration.
See the jmx
plugin documentation for more details.
Many applications need to send email, and the JavaMail API provides a robust implementation of this. Itâs not the easiest API to use, but luckily, the Spring support for sending email using JavaMail makes it a lot more straightforward, and the Grails mail
plugin makes it painless to send plain-text and HTML emails, add attachments, and even use GSP templates.
See the mail
plugin documentation for more details.
The cache abstraction feature was added to Spring in version 3.1, so applications using Grails 2.0 or higher can use it. This is an API for caching method calls, typically those that are slow or resource-intensive but that return the same result given the same parameter values.
This has been implemented in Grails in plugins; there is a âcoreâ cache
plugin that provides an in-memory implementation, and extension plugins including cache-ehcache
and cache-redis
that use Ehcache and Redis, respectively, to implement the caching logic.
Method call caching is supported in Spring beans (typically Grails services) by using the Spring org.springframework.cache.annotation.Cacheable
, org.springframework.cache.annotation.CachePut
, and org.springframework.cache.annotation.CacheEvict
annotations.
The core plugin also has annotations with the same names in the expectation that we can add additional parameters above what Spring supports in the future. The plugins also add web-tier caching for controller actions (for annotated controller methods, but not closures) and GSPs, using the <cache:block>
and <cache:render>
tags.
See the documentation for the caching plugins for more details about how to use them in your applications.
Get Programming Grails now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.