Grails Anti-Pattern: Everything is a Service

The context

Grails makes it very easy to put any logic of your application in a service. Just grails create-service and you’re good to go. There’s a single instance by default, injectable anywhere. Powerful stuff and makes it easy to get up ’n running very fast!

Creating a new application, following so-called “best practices” from blogs like these 🙂 and the ‘idiomatic Grails-way’ described in the docs and in tutorials work in the beginning, but there’s always a tipping point — where the application has grown a reasonable size — where one should start following a different, maybe less-Grailsey, strategy.

A team really took this advice to heart and started centralising their Album queries in a AlbumService, their Product queries in a ProductService and so on.

Here’s what I saw happening.

Sprint 1: Life is beautiful

This team started out really sharp: they almost were implementing business-like logic in controllers, but could pull those into services just in time. The grails create-service command would even immediately create an empty unit test — ready to implement.

The productivity was unparalleled. The team never had to manually create a class anymore with their IDEs and for the next sprints the team burned through the backlog like a hot knife through the butter.

Fast-forward 6 sprints.

Sprint 6

Looking at their code, it seems their services folder consists of a dozens of classes:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

grails-app/services/

└──example

├──AnotherProductService.groovy

├──...

├──OrderService.groovy

├──OrderingService.groovy

├──...

├──Product2Service.groovy

├──ProductAccountingService.groovy

├──ProductBuilderService.groovy

├──ProductCatalogService.groovy

├──ProductCreateService.groovy

├──ProductFinderService.groovy

├──ProductLineFileConverterDoodleService.groovy

├──ProductLineMakerService.groovy

├──ProductLineReaderService.groovy

├──ProductLineService.groovy

├──ProductLineTaglibHelperService.groovy

├──ProductLineUtilService.groovy

├──ProductManagementService.groovy

├──ProductManagerService.groovy

├──ProductMapperService.groovy

├──ProductOrderService.groovy

├──ProductReadService.groovy

├──ProductSaverService.groovy

├──ProductService.groovy

├──ProductTemplateOrderBuilderService.groovy

├──ProductUtilService.groovy

├──ProductWriterService.groovy

├──ProductsReadService.groovy

├──ProductsService.groovy

└──...

1directory,532files

The pattern

This happened to me a gazillion times before. Me and the team value the simplicitly and power of Grails. Hence, it’s pretty easy to start using the Grails commands to the fullest, such as all the create-* commands:

1

2

3

4

5

6

7

8

grails>create-

create-command create-controller

create-domain-classcreate-functional-test

create-integration-test create-interceptor

create-scaffold-controller create-script

create-service create-taglib

create-unit-test

In many Grails projects, similar to the fictional one 🙂 above, the create-service command has been over-used, because it seems to be idiomatic way of creating “business logic in the service layer”.

Yes, this command does create a nice, empty unit test, and is automatically a handy Spring bean injectable in controllers, tag libraries and other Grails artefacts.

Yes, using a *Service works well in blog posts, demo’s and tutorials.

However, it seems that we have forgotten basically everything is a “service” to someone else, but that we do not necessarily need to postfix (“Service”) every class as such.

Seems that people usually understand when something needs to be a controller (“let’s do create-controller“) or a tag library (“let’s do create-taglib“) and so forth, and for everything else: boom!, “let’s do create-service“.

In any other, non-Grails project we’re used to calling a builder simply “PersonBuilder”, in Grails projects it’s suddenly “PersonBuilderService”. In any other project a factory is a “PersonFactory”, in a Grails project it’s a weird “PersonFactoryService”.

What if a “PersonReadService” is responsible for getting or finding persons? For years people having been using the Repository pattern for this and this can be reflected with a “Repository” postfix, e.g. “PersonRepository”.

Even in Grails a builder can be a Builder, a factory a Factory, a mapper a Mapper, a repository a Repository, a doodle a Doodle and whatever can end in Whatever — you can name every class the way you want.

What we can we do about it?

Stop calling everything a Service

First, next time you’re about to create a class following one of the Famous Design Patterns, such as Builder, Factory, Strategy, Template, Adapter, Decorator (see sourcemaking.com for a nice overview), or other “well-known” Java (EE) patterns, such as Producer or Mapper or something, ask yourself a question:

Can it be a regular class in src/main/groovy?

Move and choose a better name

Yes, then just create the class in src/main/groovy. Maybe choose a nice package, such as example. If you don’t want 532 classes in one package, you can always introduce sub-packages such as example.accounting. Give it a name which does not end in *Service. Don’t forget to manually add an associated *Spec in src\test\groovy.

Do you still want to have the benefit of Spring and Dependency Injection?

In other words, do you need an instance of your class to be able to be injected into any Grails classes, such as a controller, as you are used to with a service, like the ProductReadService below?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// grails-app/controllers/example/HomepageController.groovy

classHomepageController{

ProductReadService productReadService

def index(){...}

}

// grails-app/services/example/ProductReadService.groovy

classProductReadService{

SecurityService securityService

Product findByName(Stringname){

assertsecurityService.isLoggedIn()

Product.findByName(name)

}

}

The underlying container is created by the Spring Framework.

There’s a great chapter in the docs about Grails and Spring. It’s this framework that will instantiate for example one SecurityService in the application, inject it in the “securityService” property when it creates one instance of ProductReadService which it injects in the HomepageController and so forth.

The SecurityService in the example — which might come from a Security plugin and the *Service classes in your own application sources – they’re all automatically picked up and managed by the Spring container and injected in every other managed class that needs it.

It’s not so much the move of grails-app/services/example to the src/main/groovy/example folder, but by renaming a class to something which doesn’t end in “Service” anymore, that’s when you lose the automatic management by Spring. This happens when we, as suggested, after the move, rename the class ProductReadService to a ProductRepository class.

Yes, it want them to be a Spring bean!

Declaring Spring beans the Grails way

Sure, we can do this ourselves. The Grails idomatic way is to specify beans in resources.groovy.

1

2

3

4

5

6

7

8

// grails-app/conf/spring/resources.groovy

import example.*

beans={

productRepository(ProductRepository){

securityService=ref('securityService')

}

}

We’ve defined a a bean named “productRepository” of class ProductRepository and we’ve indicated the SecurityService needs to be injected.

This is how the original code has changed, but the behaviour has not: it’s now using ProductRepository instead.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// grails-app/controllers/example/HomepageController.groovy

classHomepageController{

ProductRepository productRepository

def index(){...}

}

// src/main/groovy/example/ProductRepository.groovy

classProductRepository{

SecurityService securityService

Product findByName(Stringname){

assertsecurityService.isLoggedIn()

Person.findByName(name)

}

}

This is not the only way to declare Spring beans.

Declaring Spring beans the Spring way

We declared Spring beans the Grails way, but we can also declare beans the Spring way.

Ok, there’s not just “a Spring way”, there are many ways, from the old XML declarations, classpath scanning to Java-style configuration.

Having (a subset of) your 532 classes in resources.groovy might be considered not all that better than the XML configuration Spring used in the early days.

Even through the Beans DSL is a lot more powerful here than XML ever was (because: Groovy), we’re not transitioning our automatically picked up service beans to get manual labour back, in my opinion. 😉

This is how it would look:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

beans={

anotherProductRepository(AnotherProductRepository){

securityService=ref('securityService')

orderingService=ref('orderingService')

}

productLineReader(ProductLineReader)

productFinder(ProductFinder){

productRepository=ref('productRepository')

productLineService=ref('productLineService')

}

productRepository(ProductRepository){

securityService=ref('securityService')

productReader=ref('productReader')

productWriter=ref('productWriter')

}

orderingService(OrderingService){

securityService=ref('securityService')

productRepository=ref('productRepository')

}

...

There are use cases where resources.groovy is perfectly fine, but why not get rid of the boiler-plate and leverage the modern features of Spring at our disposal?

This makes Spring, at application startup, scan all components on the classpath under the package “example” and register them as Spring beans. Or specify @ComponentScan("example") to be more explicit.

What are these “components” you say?All classes annotated with Spring’s stereotype annotation @Component. Or @Service or @Repository which are just specializations.

Annotate our classes to make them candidate for auto-detection.

1

2

3

4

5

6

7

8

9

10

import org.springframework.stereotype.Component

@Component

// or @Repository in this particular case

classProductRepository{

SecurityService securityService

Product findByName(Stringname){..}

}

At the moment, when we would restart our app, we’ll get at NullPointerException when we try to invoke anything on securityService.Spring no longer recognizes it should do something with the property — it’s just a mere property now. To make the SecurityService be injected by Spring we need to annotate the property with Spring’s @Autowired, but that’s basically the same as the setter-injection we already had in the beginning. And @Autowired is boiler-plate we don’t need.

While we’re at it, I recommend to use constructor-injection, which means we create (or let the IDE create) a constructor. * We make the dependencies of ProductRepository explicit. * Spring will automatically “autowire” our constructor as long as we have exactly one, and inject all parameters of the constructor

1

2

3

4

5

6

7

8

9

10

import org.springframework.stereotype.Component

@Component

classProductRepository{

finalSecurityService securityService

ProductRepository(SecurityService securityService){

this.securityService=securityService

}

This is it.

BTW having an explicit constructor with all the mandatory dependencies, is always a good practice — whether it’s a Spring bean or not.

Finally, revert resources.groovy to its initial, empty state – we’re not using it anymore.

Naming is important

Now, if we would have done this to the original, 532 classes we might end up with a more enjoyable tree of files. E.g.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

grails-app/services/

└──example

├──OrderService.groovy

├──ProductService.groovy

└──SecurityService.groovy

src/main/groovy/

└──example

├──order

│ ├──OrderBuilder.groovy

│ └──OrderRepository.groovy

└──product

├──ProductBuilder.groovy

├──ProductFinder.groovy

├──ProductLineReader.groovy

├──ProductLineTaglibHelper.groovy

├──ProductMapper.groovy

├──ProductRepository.groovy

├──ProductUtils.groovy

└──ProductWriter.groovy

Some actual *Service classes cal still reside in grails-app/services and the rest can become clearly named classes, neatly placed in src/main/groovy, while you still enjoy the benefit of using them as Spring beans.

If you and the team early on in the process decide on proper naming conventions (packages, class prefixes and such), you don’t have to reorder everything like we did just now. Together with the team, create and name your classes in an organized place.