Hotfixing Code running inside Web Container with Groovy
- by raoulsson
I have a webapp running that has a bug. I know how to fix it in the sources. However I cannot redeploy the app as I would have to take it offline to do so. (At least not right now).
I now want to fix the code "at runtime". Surgery on the living object, so to speak.
The app is implemented in Java and is build on top of Seam. I have added a Groovy Console to the app previous to the last release. (A way to run arbitrary code at runtime)
The normal way of adding behaviour to a class with Groovy would be similar to this:
String.metaClass.foo= { x -> x * x }
println "anything".foo(3)
This code added the method foo to java.lang.String and prints 9. I can do the same thing with classes running inside my webapp container. New instances will thereafter show the same behaviour:
com.my.package.SomeService.metaClass.foo= { x -> x * x }
def someService = new com.my.package.SomeService()
println someService.foo(3)
Works as excpected. All good so far.
My problem is now that the container, the web framework, Seam in this case, has already instantiated and cached the classes that I would like to manipulate (that is change their behaviour to reflect my bug fix).
Ideally this code would work:
com.my.package.SomeService.metaClass.foo= { x -> x * x }
def x = org.jboss.seam.Component.getInstance(com.my.package.SomeService)
println x.foo(3)
However the instantiation of SomeService has already happened and there is no effect.
Thus I need a way to make my changes "sticky". Has the groovy magic gone after my script has been run? Well, after logging out and in again, I can run this piece of code and get the expected result:
def someService = new com.my.package.SomeService()
println someService.foo(3)
So the foo method is still around and it looks like my change has been permanent...
So I guess the question that remains is how to force Seam to re-instantiate all its components and/or how to permanently make the change on all living instances...?