Monkey patching


(Nick Pomfret) #1

How can I create a java source set that sits at the front of my class path. I need one so that I can “monkey-patch” some classes from other another project that sits in a jar in my regular classpath. The patched class files need to be at the start of the class path so that the runtime doesn’t pick those classes up from the jar and instead uses mine.


(René Groeschke) #2

You should be able to do something like this:

sourceSets {
    monkeyPatch {
    }
    main {
        runtimeClasspath = sourceSets.monkeyPatch + runtimeClasspath
    }
}

This would mean that you need your patched sources be living in src/monkeypatch/java

My question would be why can’t you fix your classes in the original place.
Wouldn’t you still see those runtime issues in production once you have published your library?


(Nick Pomfret) #3

Thanks for the response, I’ll give that a go.

The reason I can’t fix in the original place… well I can, and I will. But submitting a PR and waiting for a release can take a while, and I need a way to get these changes into my project quickly. Also, making the changes in-place (inside my project), is a quick way to test them out.

I won’t see these issues at runtime because my runtime class path will include the classes compiled from the monkey-patch source tree.


(uklance) #4

I think it’s better to create a new jar with the patched class files rather than having to rely on classpath ordering.

I just tried a proof of concept here where anything in src/main/java or src/main/resources will override files in the spring-context jar.

In a consumer project you would depend on the patch project instead of the original jar. I tested by putting println in ClasspathXmlApplicationContext constructor. Works well, all transitive dependencies are maintained


(uklance) #5

I turned the gist into a plugin to simplify things. Plugin here, sample usage here

apply plugin: 'com.lazan.java-monkey-patch'

monkeyPatch {
	target = 'org.springframework:spring-context:4.3.9.RELEASE'
}

(René Groeschke) #6

very nice effort lance! :smiley: