grails callback when controller recompiled in runtime - grails

I am overwriting the redirect method of every controller I wrote. I did that because
a) I need to set some variables before the redirect is actually executed
b) I want to do that globally because it is the same code for every controller and I want to be DRY
I did this in the bootstrap because it is executed when the server starts.
Code:
grailsApplication.controllerClasses.each() { controllerClass ->
if (controllerClass.fullName.startsWith("my.package")){
def oldRedirect = controllerClass.metaClass.pickMethod("redirect", [Map] as Class[])
controllerClass.metaClass.redirect = { Map args ->
// pre-redirect logic
args.put("some", "property")
oldRedirect.invoke delegate, args
// post-redirect logic
}
}
}
Here is the problem:
When I am developing, I use the reloading feature / just in time compiler which recompiles the file without the need to restart the server. In this case the controller is rebuilt and as a result the overwritten redirect method is lost.
Here is the question:
Is there a callback / another way to find out when a class is recompiled in runtime? I would love to check if a controller was rebuild and then overwrite the redirect method again!

Yes, break this functionality out into a plugin and you can then observe reloading of classes and re-apply your changes. The documentation goes into great detail on participating in auto reload events.
This would be the cleanest, and most proper way to accomplish what you are looking to do.

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!

Execute controller method on startup (Grails)

I have an event controller with a populate() method which adds events from a JSON link to my database. I want this to occur on startup of my server.
I've tried various things in my Bootstrap file. Such as:
def event = new EventController.populate()
You really should move that code into a service and out of your controller. This gives you a lot more options, including injecting the service into your Bootstrap.groovy and calling the method on startup of the application.
That's a much more proper Grails solution.

Caching state with Grails controllers

I understand that Grails strives very hard to be stateless, however I have a need for one of my controllers to retain a particular fizz value that should be found inside every HTTP request:
class MyController {
List<Fizz> cachedFizzes = new ArrayList<Fizz>()
def index() {
Fizz fizz = extractFizz(params)
cachedFizzes << fizz
...
}
...
}
However when testing this approach locally, it seems that cachedFizzes is re-instantiated with each HTTP request, and so no matter how many times I call one of this controller's actions, the list of Fizzes never grows.
So I ask: how can I (specifically) inject MyController with a List<Fizz> that will exist and grow across the lifetime of the app (not the controller/HTTP request)?
There's rarely a need to create a new controller instance for each request, so it's best to configure them as singletons in Config.groovy:
grails.controllers.defaultScope = 'singleton'
But I think that's the default setting for Grails versions where this is configurable - what version of Grails are you using?
Another option that will work with singleton or instance-per-request controllers is to make cachedFizzes static.
Unrelated - new ArrayList<Fizz>() is way too verbose; just use []. You'll still have the self-documenting collection and generic type on the left and it will function identically.

Using NonEmptyNavigator.metaClass.invokeMethod { ... } to introduce short pause after field set

In my application, some of the Geb tests are a bit flaky since we're firing off an ajax validation http request after each form field changes. If the ajax call doesn't return fast enough, the test blows up.
I wanted to test a simple solution for this, which (rightly or wrongly, let's not get into that debate here...) is to introduce a short 100ms or so pause after each field is set, so I started looking at how & where I could make this happen.
It looks like I need to add a Thread.sleep after the NonEmptyNavigator.setInputValue and NonEmptyNavigator.setSelectValue methods are invoked. I created a subclass of GebSpec, into which I added a static initializer block:
static {
NonEmptyNavigator.metaClass.invokeMethod = { String name, args ->
def m = delegate.metaClass.getMetaMethod(name, *args)
def result = (m ? m.invoke(delegate, *args) : delegate.metaClass.invokeMissingMethod(delegate, name, args))
if ("setInputValue".equals(name) || "setSelectValue".equals(name)) {
Thread.sleep(100)
}
return result
}
}
However I added some debug logging, and I noticed that when I execute my spec I never hit this code. What am I doing wrong here...?
I know you asked not to get into a debate about putting sleeps whenever you set a form element value but I just want to assure you that this is really something you don't want to do. There are two reasons:
it will make your tests significantly slower and this will be painful in the long run as browser tests are slow in general
there will be situations (slow CI for instance) where that 100ms will not be enough, so in essence you are not removing the flakiness you are just somehow limiting it
If you really insist on doing it this way then Geb allows you to use custom Navigator implementations. Your custom non empty Navigator implementation would look like this:
class ValueSettingWaitingNonEmptyNavigator extends NonEmptyNavigator {
Navigator value(value) {
super.value(value)
Thread.sleep(100)
this
}
}
This way there's no need to monkey-patch NonEmptyNavigator and you will avoid any strange problems that might cause.
A proper solution would be to have a custom Module implementation that would override Navigator value(value) method and use waitFor() to check if the validation has completed. Finally you would wrap all your validated form elements in this module in your pages and modules content blocks. This would mean that you only wait where it's necessary and as little as possible. I don't know how big your suite is but as it will grow these 100ms will turn into minutes and you will be upset about how slow your tests are. Believe me, I've been there.

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