Your business logic will be invoked only in the context of a Hibernate transaction, therefore anything that may modify the data should be transactional. This is a vast topic, thankfully well covered in the Grails documentation and in the Spring documentation.
There are many ways to ensure that a transaction is used: some declarative, some procedural. They are all equally valid: the only thing that matters is that objects be created, changed or deleted in the context of a transaction.
One thing not to do is declare your controller class as transactional. This is because controllers get called many times, and assigning the
If a constraint fails, it might be nice to show a friendly message to the user. By default, the user will see the default error page, which is not really appealing.
Be aware that Automated Business logic exceptions are raised at commit time, not save time. So, you must catch exceptions at that point.
One possible approach would be to use a programmatic transaction:
This approach, one of many possible, allows Grails to be notified of the failure, and of which attribute caused the problem, so that it can be highlighted in the UI:
A less flexible, but more general, approach might be to use Grails' response code mapping. By having the following in your UrlMappings.groovy:
you will ensure that, by default, all constraint violations will be routed to the given controller, which might do something like:
This code is obviously very simplistic, but is meant to inspire more sophisticated approaches.
You can use STS and its debugging services, but take note of proxy implications.