| title: Why You Should Avoid Using Autowiring for Grails® Domain Classes | |
| date: May 9, 2017 | |
| description: Autowiring a service into a domain class can have a big performance impact. | |
| author: Sergio Del Amo Caballero | |
| image: 2017-05-09.jpg | |
| CSS: [%url]/stylesheets/prism.css | |
| JAVASCRIPT: [%url]/javascripts/prism.js | |
| --- | |
| # [%title] | |
| [%author] | |
| [%date] | |
| Tags: #gorm | |
| You should not inject services into a domain class. | |
| Why? | |
| Autowiring a service into a domain class can have a big performance impact. | |
| Imagine you query 1,000 records from a database, and those records are mapped into a GORM entities. Injecting a service into each of those 1,000 GORM entities will have a performance cost. | |
| Thus, [starting with Grails<sup>®</sup> 3.2.8](https://github.com/grails/grails-core/releases/tag/v3.2.8) auto wiring of GORM entities is disabled when you create an app from scratch. In Grails 3.3.0 or above it is disabled by default. | |
| Let me illustrate this with an example. | |
| The following code will not get the service _greetingService_ injected into a domain class unless you enable auto wiring. | |
| ```groovy | |
| package demo | |
| class Greeter { | |
| def greetingService | |
| String name | |
| String sayHello() { | |
| "${name}${greetingService.sayHi()}" | |
| } | |
| } | |
| package demo | |
| class GreetingService { | |
| String sayHi() { | |
| 'Hello' | |
| } | |
| } | |
| package demo | |
| class HelloController { | |
| def index() { | |
| def person = new Greeter(name: 'Sergio') | |
| render person.sayHello() | |
| } | |
| } | |
| ``` | |
| If you are autowiring services into your domain instances as in the above example, you will need to re-enable it. | |
| For versions of Grails 3.3.0 or above, you can turn on autowire on a single domain class: | |
| grails-app/domain/demo/Book.groovy | |
| ```groovy | |
| ---- | |
| class Book { | |
| BookService bookService | |
| String name | |
| static mapping = { | |
| autowire true | |
| } | |
| ... | |
| .. | |
| . | |
| } | |
| ``` | |
| You can turn on autowire for all your domain classes using the [Default Mapping](https://gorm.grails.org/latest/hibernate/manual/index.html#_the_default_mapping_constraints%5BDefault) setting: | |
| grails-app/conf/application.groovy | |
| ```groovy | |
| ---- | |
| grails.gorm.default.mapping = { | |
| autowire true | |
| } | |
| ``` | |
| For versions below Grails 3.3.0, you can re-enable it changing the _grails.gorm.autowire_ configuration parameter. | |
| grails-app/conf/application.yml | |
| ``` | |
| ---- | |
| grails: | |
| gorm: | |
| autowire: true | |
| ``` | |
| **If Spring autowiring of domain instances is enabled, read performance will degrade.** | |
| Try to avoid the injection of services in domain classes. the Grails framework has an excellent services layer. You should place your business logic there. | |