18.10 The Artefact API - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 3.1.8
18.10 The Artefact API
You should by now understand that Grails has the concept of artefacts: special types of classes that it knows about and can treat differently from normal Groovy and Java classes, for example by enhancing them with extra properties and methods. Examples of artefacts include domain classes and controllers. What you may not be aware of is that Grails allows application and plugin developers access to the underlying infrastructure for artefacts, which means you can find out what artefacts are available and even enhance them yourself. You can even provide your own custom artefact types.18.10.1 Asking About Available Artefacts
As a plugin developer, it can be important for you to find out about what domain classes, controllers, or other types of artefact are available in an application. For example, the Searchable plugin needs to know what domain classes exist so it can check them for anysearchable
properties and index the appropriate ones. So how does it do it? The answer lies with the grailsApplication
object, and instance of GrailsApplication that's available automatically in controllers and GSPs and can be injected everywhere else.The grailsApplication
object has several important properties and methods for querying artefacts. Probably the most common is the one that gives you all the classes of a particular artefact type:for (cls in grailsApplication.<artefactType>Classes) {
…
}
artefactType
is the property name form of the artefact type. With core Grails you have:
- domain
- controller
- tagLib
- service
- codec
- bootstrap
- urlMappings
for (cls in grailsApplication.domainClasses) {
…
}
for (cls in grailsApplication.urlMappingsClasses) {
…
}
Class
:
shortName
- the class name of the artefact without the package (equivalent ofClass.simpleName
).logicalPropertyName
- the artefact name in property form without the 'type' suffix. SoMyGreatController
becomes 'myGreat'.isAbstract()
- a boolean indicating whether the artefact class is abstract or not.getPropertyValue(name)
- returns the value of the given property, whether it's a static or an instance one. This works best if the property is initialised on declaration, e.g.static transactional = true
.
- get<type>Class(String name)
- is<type>Class(Class clazz)
GrailsClass
instance for the given name, e.g. 'MyGreatController'. The second will check whether a class is a particular type of artefact. For example, you can use grailsApplication.isControllerClass(org.example.MyGreatController)
to check whether MyGreatController
is in fact a controller.
18.10.2 Adding Your Own Artefact Types
Plugins can easily provide their own artefacts so that they can easily find out what implementations are available and take part in reloading. All you need to do is create anArtefactHandler
implementation and register it in your main plugin class:class MyGrailsPlugin { def artefacts = [ org.somewhere.MyArtefactHandler ] … }
artefacts
list can contain either handler classes (as above) or instances of handlers.So, what does an artefact handler look like? Well, put simply it is an implementation of the ArtefactHandler interface. To make life a bit easier, there is a skeleton implementation that can readily be extended: ArtefactHandlerAdapter.In addition to the handler itself, every new artefact needs a corresponding wrapper class that implements GrailsClass. Again, skeleton implementations are available such as AbstractInjectableGrailsClass, which is particularly useful as it turns your artefact into a Spring bean that is auto-wired, just like controllers and services.The best way to understand how both the handler and wrapper classes work is to look at the Quartz plugin:
Another example is the Shiro plugin which adds a realm artefact.