The fix code works inside a web container with Groovy

I have a webapp running which has a bug. I know how to fix this in sources. However, I cannot redeploy the app as I would have to disable it offline. (At least not now).

Now I want to fix the code "at runtime" . Surgery on a living object, so to speak.

The application is implemented in Java and built on top of Seam. I added Console to my Groovy app from a previous version. (A way to run arbitrary code at runtime)

The usual way to add behavior to a class with Groovy would be like this:

String.metaClass.foo= { x -> x * x }
println "anything".foo(3)

      

This code added a foo method to java.lang.String and prints 9. I can do the same with the classes running inside my webapp container. After that, the new instances will show the same behavior:

com.my.package.SomeService.metaClass.foo= { x -> x * x }
def someService = new com.my.package.SomeService()
println someService.foo(3)

      

Works like a verified one. Everything is fine so far.

My problem is that the container, the web framework, Seam in this case, was already instantiating and caching the classes that I would like to manipulate (this is a change in their behavior to reflect the bug fix).

Ideally, this code will 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, an instance of SomeService has already occurred and there is no effect.

Thus, I need a way to make my changes "sticky" . Did the Groovy magic work after my script? Well, after logging out and over again, I can run this piece of code and get the expected output:

def someService = new com.my.package.SomeService()
println someService.foo(3)

      

So the foo method still exists and it looks like my change was permanent ...

So my guess is that the remaining question is: to get Seam to re-create all of its components and / or how to permanently make the change in all live instances ...

+2


source to share


2 answers


The fix is ​​not permanent because the calling code is pure Java, not Groovy .

The Groovy magic really remains. But only when called from within the Groovy environment, that is, through other Groovy code.



It turns out that in Java , the Keyhole Surgery Pattern , as invented by Dierk König, can only be used to modify data at runtime, not code. The full power of the template is only available in a pure Groovy environment.

+1


source


Not Groovy, but an alternative approach that works - as long as you don't change / add / remove and sign the method signatures - is to set the server to debug mode and use the Java Hot Code Replacement feature. Most IDEs support this. Changes are permanent and apply to instantiated components as well. It is required, of course, that the application server is already configured using the debug console, or allows you to enable it after startup.



0


source







All Articles