I was looking at the sample pet clinic grails app on github.
It has a service for creating pets called PetclinicService
that has a method for adding pets:
Pet createPet(String name, Date birthDate, long petTypeId, long ownerId) {
def pet = new Pet(name: name, birthDate: birthDate, type: PetType.load(petTypeId), owner: Owner.load(ownerId))
pet.save()
pet
}
which is being used from the controller like so:
def pet = petclinicService.createPet(params.pet?.name, params.pet?.birthDate,
(params.pet?.type?.id ?: 0) as Long, (params.pet?.owner?.id ?: 0) as Long)
I'm curious to know whether this is the best way to save something in grails? With this approach if I add another field to the Pet
domain, say String color
, then I'll have to touch three classes (Pet, PetController, and PetclinicService
) for the change to be complete.
Is there a way I can send the entire params
object into the service and have it automatically map to the domain?
I made that change because the standard is to pass in the params
map, but this is bad for a few reasons. One is that it couples the service tier to the web tier. This isn't a strict coupling since it is just a Map, but services should be reusable and independent. The other is that the map is a "magic" map where you need to know the keys in order to use it. By using named and typed method arguments, the code is more readable and understandable.
This does add a maintenance burden since as you point out adding a new field requires changing the signature, but ideally this method will be the one place where this work is done, so you only need to change it in one place.
Feel free to use params
in your own code, but since this project is one of our demo projects I wanted it to use best practices where possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With