grails transactional controller, handling exceptions - grails

I have the following method within my controller:
#Transactional
def update(Filter filterInstance) {
bindData(filterInstance, params, [include: ['name, 'code', 'value']])
filterService.update(filterInstance)
mappingService.update(filterInstance)
respond filterInstance
}
I need to use #Transactional here because I call multiple services. How to handle case when transaction fails for some reason? Should I use try catch or may be there is some other way?
Thanks!

If you have the code inside a controller action, you have to keep an eye on 2 things:
transactionality (with try/catch/finally etc)
what should the action return/render in case of TX-success/-failure.
It's complicated enough, so you should put the service calls into another service method, where you have to deal with the transactions only.
A controller action is a place, where you may fire really simple 1-step transactions. If you need to implement a more complex TX-logic, do it on the service layer
see ref-doc on how to control multi-step transactions.
you can make your update() methods return false or throw an exception, and if such thing occurs, call status.setRollbackOnly(). Don't forget also to mark the update() methods with #Transactional(propagation = Propagation.SUPPORTS)

Related

Is there a way to add a virtual method behaviour for every controller method? (i.e logging)

After my research, my own answer to my question is: unfortunately, no. But I'd like to hear your opinion as well.
I have 4 controllers each having 5 methods. Every method has a try-catch block. In case of an exception, I want to log on a file a message with all the parameters of that controllers. So I have to write the basically same log instruction 4x5=20 times. If I want to change the logging message, I have to do it 20 times. On one hand, sounds like a hard to maintain problem. But on the other hand, every controller has its own signature.
Would it be possible to have some base/parent/God method that virtually logs for every controller? And of course if I will be needing to adapt/override the logging instruction just for one controller this should be also possible. Is there any technique?
How about if I just need to generate for every controller methods a GUID?
There are many ways to achieve a single piece of code that can log all your controller methods. The easiest implementation which comes to my mind is to just write a method that takes an action or function. Then inside just call that action/function and wrap it in any logging that you wish to use. Like so:
public void ExecuteWithLogging(Action actionToExecute)
{
try
{
action() // the same as action.Invoke()
}
catch(Exception e)
{
// code your logging here
}
}
then inside your controller's methods you could use it like this:
ExecuteWithLogging(() =>
{
// your controller code
});
But there are other ways. You could probably use attributes to mark each method as logged. Or maybe you could write some middle-ware that just logs everything (like maybe in this article -> https://exceptionnotfound.net/using-middleware-to-log-requests-and-responses-in-asp-net-core/).
The options are many!

afterUpdate event hook, transactions, and old state in consecutive requests

We're running into a weird issue where objects are created in a first request, but they are not returned in a second request.
Let's assume we have two domain classes:
Class A {
static hasMany = [bs: B]
def afterUpdate() {
this.addToBs(new B(a: this))
this.save()
}
}
Class B {
static belongsTo = [a: A]
}
When a put is sent on an instance of A via PUT /as/<id>, update() is invoked in the RestfulController which is annotated with #Transactional.
What we can observe is, that every once in a while a follow-up request send by the API consumer after the response of the first request is returned, GET /bs does not return the new instance of B which should have been created in the first request and is also returned on further requests.
I'd expected that grails only sends the response to the API consumer once the transaction is committed, which would mean that the next request should see all changes from that transaction, shouldn't it?
What could be the reason for that behavior? Is the transaction committed after the grails app already sent the response to the API consumer? If so, is the reason the #Transactional around the update() which is turned on by default?
I know in this example the code in afterUpdate could probably also be put into beforeUpdate, but I just tried to to simplify the example as far as I could.
In my experience, code in afterUpdate() and the like are not included in the transaction. You'd have to create a transaction explicitly (and maybe a session too). See http://docs.grails.org/latest/ref/Domain%20Classes/withTransaction.html
I advise against GORM updates within afterUpdate() and friends because it leads to weird issues like this, and makes it difficult to unit test the domain models. If you delegate saving to a transactional service instead, not only would it just work, you'd also be able to confirm it with integration tests.
In my Grails apps, I keep my controllers really dumb:
Call a service
Return the service's output (possibly formatting it).
I keep all business logic in services because controllers are kind of a pain to test well. Here's an example:
#grails.transaction.Transactional
class SomeService {
def saveA(A a) {
// This method will run in a transaction.
a.addToBs(new B(a: this))
a.save()
}
}
And in the controller...
class SomeController {
def update() {
...
someService.save(a)
}
}

grails how to disable transactional for a method

I have a service method to transfer funds to/from an external system.
it should create a transaction in our system first (so we have a transactionId)
Then we call the external system.
If the external system fails, we need to rollback the transaction, then write a new record in our payment audit log table, regardless of if the call failed or worked.
I cant figure out how to control the transaction in this case.
I understand services are transactional by default.
I assume I could create 3 methods (they are all 1 method now, which doesn't work as I have no control over what gets committed and what gets rolled back)
createPaymentTransaction()
sendToPaymentSystem()
createPaymentRecord()
I need to rollback 1 if 1 fails, and do nothing more.
I need to rollback 1 if 2 fails, but write 3.
I need to write 3 if 1 and 2 works.
I don't know how to annotate these, or how to structure a 4th request to manage the 3.
I'd go with something like this:
package com.myapp
import grails.transaction.Transactional
import org.springframework.transaction.annotation.Propagation
#Transactional
class MyService {
def createPaymentTransaction() {}
def sendToPaymentSystem() {}
#Transactional(propagation=Propagation.REQUIRES_NEW)
def createPaymentRecord() {}
def method4() {
try {
def transactionId = createPaymentTransaction()
sendToPaymentSystem(transactionId)
}
finally {
createPaymentRecord()
}
}
}
By annotating at the class level, we set the defaults for all methods, but can customize as needed, e.g. for createPaymentMethod.
So what will happen is that calling method4 will join an existing transaction, or start a new one if necessary. If there's a problem in either createPaymentTransaction or sendToPaymentSystem then the transaction will be rolled back, but the call to createPaymentRecord will happen because it's in the finally block, and it will run in a separate transaction so it isn't affected by a rollback in the main transaction, and a failure there doesn't affect the main transaction.
If you're not able to use the new grails.transaction.Transactional annotation, use the standard Spring org.springframework.transaction.annotation.Transactional annotation, but you need to make a small change. One of the motivations for the Grails annotation is to provide the same functionality as the Spring annotation, but avoid the problems with calling an annotated method from within the service. The Spring annotation triggers creation of a proxy at runtime which intercepts all calls, manages transactionality for the method, and then calls the real method in the service instance. But with the current code, the call to createPaymentRecord will bypass the proxy (the service instance is just calling itself) and there won't be a new transaction. The Grails annotation rewrites the bytecode to wrap each method in a transaction template which uses the applicable annotation settings (explicit or inferred from a class-scope annotation), so it works correctly internally and externally. If using the Spring annotation, you need to call the method on the proxy, which just involves accessing the Spring bean for this service. Add a dependency injection for the GrailsApplication as a field:
def grailsApplication
and then call createPaymentRecord via
grailsApplication.mainContext.myService.createPaymentRecord()
in the finally block.
By default all methods in a service are transactional, but you can change the behaviour on a method-by-method basis with annotations, e.g.
import grails.transaction.*
// By default all methods are transactional
#Transactional
class MyService {
#NotTransactional
def notTransactional() {
}
// inherits the class-level default
def transactional() {
}
}
See the Grails manual for more details about the transaction annotations.
If you need to manage transactions at a more fine-grained level than per-method, you can use the withTransaction domain class method to manage transactions programatically.

How to catch exceptions in grails REST controllers

If you use a controller to implement rest APIs, you want to deal with any exception thrown and return a generic or specific well formed REST response.
We can't use global error URL mapping method, as the application has a number of APIs and interfaces with different response requirements, and we also don't know which type of Grails' HTTP error codes will be thrown (e.g don't know if it will be a 400, 422, 500 etc). Also, if we used the error page mappings, we won't be able to put relevant data into the JSON response.
E.g. this will generate a GrailsRuntimeException:
class SomeController {
def payload = request.JSON
def someMethod() {
BigDecimal x = new BigDecimal(payload.notExists)
}
The problem is, it seems impossible to catch any error thrown.
E.g. neither this approach:
def handleRuntimeException(RuntimeException e) {
render("some JSON error message")
}
Nor this approach:
try {
:
}
catch (GrailsRuntimeException e) {
render("some JSON error message")
}
Works - it never catches the error.
Tried GroovyRuntimeException, Exception, MissingMethodException, Throwable etc.
The only solution we can think of is to not do any work in the controller, do everything in a service, where apparently we can catch errors.
This approach:
static mappings = {
"500"(controller: "error")
}
Is not want we need for several reasons:
We have several different APIs in different controllers which would require different response formats.
we also have UI controllers, which would want the default error system which shows the stack trace etc.
We want to handle the error in the controller where the exception happened, so we can clean up, or at least can log or return the stat which only the controller knows.
Have decided the only way is to move all code into services, and do nothing in the controller except pass the request, and render the resultant string. i.e. all parameter handling, especially number conversion, is done in the service.
It's ironic that the solution that you see as suboptimal that you're settling for is exactly what you should always do. This isn't PHP - don't put logic in Controllers (or GSPs).
Services are by default transactional, so they're a great place to put code that writes to the database since that should always happen in a transaction. They're also excellent for business logic whether it's transactional or not, and you can either annotate individual methods with #Transactional to partition the methods into ones that run in a transaction and ones that don't, or split the services into some that are fully transactional and some that aren't.
If you keep all of the HTTP-related code in the controllers, doing the data binding from params, and calling helper classes (services, domain classes, taglibs, etc.) you get a good separation of concerns, and if the service layer doesn't know anything about params, HttpServletRequest, HTTP sessions, etc. then it's easily reusable in other Grails apps and even in non-Grails apps. They'll also be easier to test, since there isn't so much inter-related code that needs to be mocked and otherwise made test-friendly.
Using this approach, the controllers basically become dumb routers, accepting requests, calling helpers to do the real work, and delegating page rendering or response writing, or redirecting or forwarding.
I am very late to answer this, but I think it might help people stumbling and searching for solution.
Here is one of my blogs explaining Custom exception handling in grails and error responses for RESTfull services
Hope this might help someone
I am using grails 3.2.4 and there is no issue as you have explained here. I have moved all business logics inside the service class and catching exceptions by parent controller trait. Here I am handling this exception in another ParentExceptionController trait which is implemented by classes where such exception is occurring from service class. Example:
UserService {
boolean create(Map params) {
throw new InvalidParameterException('some message')
}
UserController implements ParentExceptionController {
UserService userService
userService.create(params.userDetails)
}
trait ParentExceptionController {
Object handleInvalidParameterException(InvalidParameterExceoption exception) {
log.error 'log message'
respond([message: exception.message])
}
first and second both are working in my case.

Why are Controller Constructors fired before the Initialize method

I have a base Controller ApplicationController that needs to grab the URL Host and do some processing before the child controllers are fired. Since controller constructors are fired before RequestContext is initialized I have to override Initialize method to do my processing.
ApplicationController:
Protected Overrides Sub Initialize(ByVal requestContext As System.Web.Routing.RequestContext)
MyBase.Initialize(requestContext)
Dim host as String
host = Request.Url.Host.ToString
End Sub
What is the logic behind having Controller Constructors fire before the Initialize method?
Also what are the rules to what should be placed in the Initialize Method.
Assuming that constructors are the first instance method ever to be fired in a .NET class, that shouldn't come as a surprise and is not really something MVC specific. It's more how the .NET framework works.
The MVC framework needs to first instantiate a controller and then initialize it => it calls the constructor first. And because performing lots of code that could potentially might throw exceptions, etc... is not always best to be put in a constructor => the presence of the Initialize method. As far as this method is concerned I must admit that I have written lots of ASP.NET MVC code and never had to use it. Action filters always seemed like a better alternative.
So to answer your question:
Also what are the rules to what should be placed in the Initialize Method.
I've never ever put any code and never ever need to override this method. I've always preferred using action filters because this way I am no longer in the obligation of deriving from a common base controller (not that this is a problem).
Sometimes, maybe you would want your request to initialize your variables, so in this case you should use the Initialize method.
For example, if you want to initialize some variables in a different way when the request is local or not, etc.

Resources