Java - "intercept" a private method - java

I know this has been asked before, and the answer is usually "you can't" and/or "don't," but I'm trying this anyway.
The context is that I'm trying to set up some "black magic" to aid in testing. My code is running ultimately under JUnit and the nature of the system is such that, while I have access to most any library I could want (ByteBuddy, Javassist, etc), I can't play around with the code prior to it running, I'm stuck with working with classes on the fly.
Here's the setup:
// External Library that I have no control over:
package com.external.stuff;
/** This is the thing I ultimately want to capture a specific instance of. */
public class Target {...}
public interface IFace {
void someMethod();
}
class IFaceImpl {
#Override
void someMethod() {
...
Target t = getTarget(...);
doSomethingWithTarget(t);
...
}
private Target getTarget() {...}
private void doSomethingWithTarget(Target t) {...}
}
Within my test magic-ness, I have an instance of IFace, which I happen to know is an IFaceImpl. What I'd like to do is be able to steal the instance of Target produced internally. Effectively, this would have the same effect as the following (if private methods were overrideable):
class MyIFaceImpl extends IFaceImpl{
private Consumer<Target> targetStealer;
#Override
void someMethod() {
...
Target t = getTarget(...);
doSomethingWithTarget(t);
...
}
/** "Override" either this method or the next one. */
private Target getTarget() {
Target t = super.getTarget();
targetStealer.accept(t);
return t;
}
private void doSomethingWithTarget(Target t) {
targetStealer.accept(t);
super.doSomethingWithTarget(t);
}
}
But, of course, that doesn't work as private methods cannot be overridden.
So the next type of approach would be something like ByteBuddy or Javassist
public static class Interceptor {
private final Consumer<Target> targetStealer;
// ctor elided
public void doSomethingWithTarget(Target t) {
targetStealer.accept(t);
}
}
/** Using ByteBuddy. */
IFace byteBuddyBlackMagic(
IFace iface /* known IFaceImpl*/,
Consumer<Target> targetStealer) {
return (IFace) new ByteBuddy()
.subClass(iface.getClass())
.method(ElementMatchers.named("doSomethingWithTarget"))
.intercept(MethodDelegation.to(new Interceptor(t))
.make()
.load(...)
.getLoaded()
.newInstance()
}
/** Or, using Javassist */
IFace javassistBlackMagic(
IFace iface /* known IFaceImpl*/,
Consumer<Target> targetStealer) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperClass(iface.getClass());
Class subClass = factory.createClass();
IFace = (IFace) subClass.newInstance();
MethodHandler handler =
new MethodHandler() {
#Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (thisMethod.getName().equals("doSomethingWithTarget")) {
consumer.accept((Target) args[0]);
}
return proceed.invoke(self, args);
}
};
((ProxyObject) instance).setHandler(handler);
return instance;
}
and as I was testing out these pattern, it worked in other cases where the method I wanted to intercept was package-local, but not for private methods (expected for ByteBuddy, per the documentation).
So, yes, I recognize that this is attempting to invoke dark powers, and that this is normally frowned upon. The question remains, is this doable?

using javassist you can instrument the someMethod( ) in the IClassImpl class to send the instance of the TargetClass to someother class and store it there or do other manipulations using the instance created.
this can be achieved using the insertAfter( ) method in javassist .
For example :
method.insertAfter( "TestClass.storeTargetInst(t)" ); // t is the instance of Target class in IClassImpl.someMethod
TestClass{
public static void storeTargetInst(Object o){ ### code to store instance ###}
}
The insertAfter() method injects a line of code before the return statement of a method or as the last line of a method in case of void methods.
Refer this link for more information on the methods available for instrumentation.
Hope this helps!

If you can execute some code in like public static void main block, or just before IFaceImpl is loaded, then you can use javassist to edit that class directly before it is loaded - so you can change method to be public, add another one, etc:
public class Main {
public static void main(String[] args) throws Exception {
// this would return "original"
// System.out.println(IFace.getIFace().getName());
// IFaceImpl class is not yet loaded by jvm
CtClass ctClass = ClassPool.getDefault().get("lib.IFaceImpl");
CtMethod getTargetMethod = ctClass.getDeclaredMethod("getTarget");
getTargetMethod.setBody("{ return app.Main.myTarget(); }");
ctClass.toClass(); // now we load our modified class
// yay!
System.out.println(IFace.getIFace().getName());
}
public static Target myTarget() {
return new Target("modified");
}
}
where library code is like this:
public interface IFace {
String getName();
static IFace getIFace() {
return new IFaceImpl();
}
}
class IFaceImpl implements IFace {
#Override public String getName() {
return getTarget().getName();
}
private Target getTarget() {
return new Target("original");
}
}
public class Target {
private final String name;
public Target(String name) {this.name = name;}
public String getName() { return this.name; }
}
If there is no way to execute your code before that class is loaded, then you need to use instrumentalization, I will use byte-buddy-agent library to make this simpler:
public class Main {
public static void main(String[] args) throws Exception {
// prints "original"
System.out.println(IFace.getIFace().getName());
Instrumentation instrumentation = ByteBuddyAgent.install();
Class<?> implClass = IFace.getIFace().getClass();
CtClass ctClass = ClassPool.getDefault().get(implClass.getName());
CtMethod getTargetMethod = ctClass.getDeclaredMethod("getTarget");
getTargetMethod.setBody("{ return app.Main.myTarget(); }");
instrumentation.redefineClasses(new ClassDefinition(implClass, ctClass.toBytecode()));
// yay!
System.out.println(IFace.getIFace().getName());
}
public static Target myTarget() {
return new Target("modified");
}
}
Both versions might be much more problematic to run on java 9 and above due to how modules work, you might need to add additional startup flags.
Note that on java 8 instrumentalization might not be present on client JRE. (but with few more hacks can be added, even at runtime)

Related

How to create constructor in java parameterized with class?

I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}

Convenient way to create a wrapper

Problem
I need to perform logic over and over on the results of several methods. The methods can have arbitrary result types. The simple use case looks like this:
A wrapper class with an execute method:
/**
* Wrapper class which executes inner logic, processes the result of that logic and returns the processed result.
*
* #param <T>
*/
public abstract class Wrapper<T> {
/**
* Perform inner logic
*/
public abstract T run();
/**
* Invoke inner logic and process it.
*/
public T execute() {
T result = run();
// TODO: process result
return result;
}
}
And the logic in an inner class, example usage of the Wrapper:
public class WrapperDemo {
/**
* Simple invocation of the inner logic and then the outer logic
*/
public static Boolean testMethod() {
// wrap around logic and execute
return new Wrapper<Boolean>() {
#Override
public Boolean run() {
// TODO: perform logic, simply returning true for now
return Boolean.TRUE;
}
}.execute();
}
public static void main(String[] args) {
// demo method invocation
Boolean result = WrapperDemo.testMethod();
// process result
System.out.println(result);
System.exit(0);
}
}
I'll have to apply this to several 100s of methods.
Question
Does anyone know a more convenient way to code this with less code for testMethod (e. g. maybe annotation)?
If you have Java 8, you could write the following:
public static <T> T execute(Wrapper<T> wrapper) {
return wrapper.execute();
}
And then use it as following:
public static Boolean testMethod() {
return execute(()-> {
return Boolean.TRUE;
});
}
Though I fail to see how this is better than the following:
public static <T> T wrap(T result) {
// Process result
return result
}
And using it like this:
public static Boolean testMethod() {
return wrap(Boolean.TRUE);
}
If you want to use annotations, you should use a tool that allows such reflection to be used. Basic reflection can't be used because then you can't "intercept" the call. Java's Proxy might help, but you're constrained to use interfaces, which is not always what people want.
cglib is a library that removes all that hassle. With that, you can try the following:
#Target(METHOD)
#Retention(RUNTIME)
public #interface Wrap {
}
class Demo {
#Wrap
public Boolean testMethod() {
return Boolean.TRUE;
}
}
class Wrapper {
public <T> T newInstance(Class<T> type) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(type);
enhancer.setCallback(new InvocationHandler(){
#Override public Object invoke(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = proxy.invokeSuper(obj, args);
if (method.isAnnotationPresent(Wrap.class)) {
execute(result);
}
return result;
}
});
return enhancer.create();
}
public void execute(Object result) {
// Add custom behavior to #Wrap-ped methods.
}
}
Then you have to call the wrapper like this:
Demo demo = new Wrapper().newInstance(Demo.class);
demo.testMethod();
Other libraries exist too, like Byte Buddy or Javassist. But be careful because Java 9 is very close and forced those libraries into changing their core business very, very quick, possibly making them unstable.
In Java 8, by combination of lambda and default method, you can achieve similar thing without much change in your API (except you need to make Wrapper an interface instead of abstract class)
public interface Wrapper<T> {
public T run();
default public T execute() {
T result = run();
// TODO: process result
return result;
}
}
Then you can call it by
public static Boolean testMethod() {
Wrapper<Boolean> w = ()-> {return Boolean.TRUE;};
return w.execute();
}
But personally I don't think it make much sense.
If you want to add extra logic around a logic, probably what you need is a little twist:
public class ExtraAction<T> {
Supplier<T> supplier;
public ExtraAction(Supplier<T> supplier) {
this.supplier = supplier;
}
public T execute() {
T result = this.supplier.get();
// some extra processsing
return result;
}
}
so it will be called like
Boolean result = new ExtraAction<>(()->{return Boolean.TRUE}).execute();
Even better, make your logic in Wrapper a Function<X,Y>, and make up something to chain your Supplier and Function together, so it will look like
result = Foo.forInput( ()-> { return logicToGetResult(); })
.doExtra(ExtraAction::whateverAction).result();

Redirect method call at runtime to introduce some kind of sandbox

I'm in bit of a fix with this problem. Hoping for a silver bullet.
I have a few singletons(~10) which all have a few functions (~10 each). My function calls look like this (as they should). Note: Most of these calls are async and do not return anything. Only a handful are synchronous
SingletonClassGorrilla.getInstance().methodSwim(swimmingPool, lifeJacket, whistle);
SingletonClassRacoon.getInstance().methodBark(thief, owner);
I need to put all these calls in a sandbox:
Sandbox.runThisInSandboxMode(new Runnable{
#Override
public void run(){
SingletonClassGorrilla.getInstance().methodSwim(swimmingPool, lifeJacket, whistle);
}
});
As the number of places where they are being called is huge, I am hoping that the sandboxMode can be achieved at the Singleton end.
Possible solution (but infeasible because of the number of functions I will have to wrap like this):
public class SingletonClassGorrilla{
public void methodSwim(WaterBody waterBody, Instrument instrument,
EmResponse emResponse){
Sandbox.runThisInSandboxMode(new Runnable{
#Override
public void run(){
methodSwim(swimmingPool, lifeJacket, whistle, true);
}
});
}
private void methodSwim(WaterBody waterBody, Instrument instrument,
EmResponse emResponse, boolean fromSandbox){
// Do your thang.
}
}
Is there anyway, through use of reflection / annotations / any other thing in the language, which can reduce the amount of changes required?
You can use a Proxy with a suitable InvocationHandler (though you'd have to pull out an interface for each of your singletons). Disclaimer: I haven't tried to actually compile/run this code, but it should give you the general idea. If you care about return values from your singleton, you may have to use Callable instead of/in addition to Runnable in your sandbox interface.
public class SingletonGorilla implements GorillaInterface {
private static SingletonGorilla theRealGorilla;
public static GorillaInterface getInstance() {
//In reality, you'd want to store off the Proxy as well
return Proxy.newProxyInstance(SingletonGorilla.class.getClassLoader(), GorillaInterface.class, new SandboxingHandler());
}
private static class SandboxingHandler implements InvocationHandler () {
public Object invoke(Object proxy, Method method, Object[] args) {
return Sandbox.runInSandbox( new Runnable() {
public void run () {
method.invoke(proxy, args));
}
}
}
}
I'm thinking about something along the following lines:
First, you'll need an interface for each of your singletons:
Interface:
package org.test.proxywrapper;
public interface IGorilla {
public void methodSwim();
}
Implementing class:
package org.test.proxywrapper;
public class Gorilla implements IGorilla{
public void methodSwim()
{
}
}
Then, implement an InvocationHandler that factorize the code that will be common to each call to the methods of Gorilla:
package org.test.proxywrapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WrapperInvocationHandler implements InvocationHandler {
#Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Sandbox.runThisInSandboxMode(new Runnable() {
#Override
public void run() {
Object params = new Object[0];
try {
arg1.invoke(arg0, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
// return something if you need to
return new Object();
}
}
At this point, in a central place in your application/system, wrap each singleton with a Proxy, and pass the proxy reference around instead of the original wrapped object:
package org.test.proxywrapper;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String argv[])
{
WrapperInvocationHandler wrapperInvocationHandler = new WrapperInvocationHandler();
Class<?>[] implementedTypes = new Class<?>[1];
implementedTypes[0] = IGorilla.class;
IGorilla proxy = (IGorilla) Proxy.newProxyInstance(Main.class.getClassLoader(), implementedTypes, wrapperInvocationHandler);
proxy.methodSwim();
}
}
This simple example compiles and runs as I would expect.
I cut some corners here, skipped the getInstance method, etc, but I guess it gives an idea of how it can be done.

Automatically delegating all methods of a java class

Say I have a class with many of public methods:
public class MyClass {
public void method1() {}
public void method2() {}
(...)
public void methodN() {}
}
Now I would like to create a wrapper class which would delegate all the methods to wrapped instance (delegate):
public class WrapperClass extends MyClass {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
public void method1() { delegate.method1(); }
public void method2() { delegate.method2(); }
(...)
public void methodN() { delegate.methodN(); }
}
Now if MyClass has a lot of methods I would need to override each of them which is more or less the same code which just "delegates". I was wondering if it is possible to do some magic to automatically call a method in Java (so the Wrapper class would need to say "Hey if you call a method on me just go to delegate object and call this method on it).
BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final).
NOTE: I do not want IDE generation. I know I can do it with help of IntelliJ/Eclipse, but I'm curious if this can be done in code.
Any suggestions how to achieve something like this? (NOTE: I would probably be able to do it in some scripting languages like php where I could use php magic functions to intercept the call).
Perhaps the dynamic Proxy of java can help you. It only works if you consequently use interfaces. In this case, I will call the interface MyInterface and set up a default implementation:
public class MyClass implements MyInterface {
#Override
public void method1() {
System.out.println("foo1");
}
#Override
public void method2() {
System.out.println("foo2");
}
#Override
public void methodN() {
System.out.println("fooN");
}
public static void main(String[] args) {
MyClass wrapped = new MyClass();
wrapped.method1();
wrapped.method2();
MyInterface wrapper = WrapperClass.wrap(wrapped);
wrapper.method1();
wrapper.method2();
}
}
The wrapper class implementation would look like:
public class WrapperClass extends MyClass implements MyInterface, InvocationHandler {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delegate = delegate;
}
public static MyInterface wrap(MyClass wrapped) {
return (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class[] { MyInterface.class }, new WrapperClass(wrapped));
}
//you may skip this definition, it is only for demonstration
public void method1() {
System.out.println("bar");
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = findMethod(this.getClass(), method);
if (m != null) {
return m.invoke(this, args);
}
m = findMethod(delegate.getClass(), method);
if (m != null) {
return m.invoke(delegate, args);
}
return null;
}
private Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Note that this class:
extends MyClass, to inherit a default implementation (any other would do)
implements Invocationhandler, to allow the proxy to do reflection
optionally implement MyInterface (to satisfy the decorator pattern)
This solution allows you to override special methods, but to delegate all others. This will even work with sub classes of Wrapper class.
Note that the method findMethod does not yet capture the special cases.
This question is 6 months old already and #CoronA's wonderful answer has satisfied and been accepted by #walkeros, but I thought I would add something here as I think this can be pushed an extra step.
As discussed with #CoronA in the comments to his answer, instead of having to create and maintain a long list of MyClass methods in WrapperClass (i.e. public void methodN() { delegate.methodN(); }), the dynamic proxy solution moves this to the interface. The issue is that you still have to create and maintain a long list of signatures for the MyClass methods in the interface, which is perhaps a bit simpler but doesn't completely solve the problem. This is especially the case if you don't have access to MyClass in order to know all the methods.
According to Three approaches for decorating your code,
For longer classes, a programmer must choose the lesser of two evils:
implement many wrapper methods and keep the type of decorated object
or maintain a simple decorator implementation and sacrifice retaining
the decorated object type.
So perhaps this is an expected limitation of the Decorator Pattern.
#Mark-Bramnik, however, gives an fascinating solution using CGLIB at Interposing on Java Class Methods (without interfaces). I was able to combine this with #CoronaA's solution in order to create a wrapper that can override individual methods but then pass everything else to the wrapped object without requiring an interface.
Here is MyClass.
public class MyClass {
public void method1() { System.out.println("This is method 1 - " + this); }
public void method2() { System.out.println("This is method 2 - " + this); }
public void method3() { System.out.println("This is method 3 - " + this); }
public void methodN() { System.out.println("This is method N - " + this); }
}
Here is WrapperClass which only overrides method2(). As you'll see below, the non-overridden methods are, in fact, not passed to the delegate, which can be a problem.
public class WrapperClass extends MyClass {
private MyClass delagate;
public WrapperClass(MyClass delegate) { this.delagate = delegate; }
#Override
public void method2() {
System.out.println("This is overridden method 2 - " + delagate);
}
}
Here is MyInterceptor which extends MyClass. It employs the proxy solution using CGLIB as described by #Mark-Bramnik. It also employs #CononA's method of determining whether or not to send the method to the wrapper (if it is overridden) or the wrapped object (if it is not).
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyInterceptor extends MyClass implements MethodInterceptor {
private Object realObj;
public MyInterceptor(Object obj) { this.realObj = obj; }
#Override
public void method2() {
System.out.println("This is overridden method 2 - " + realObj);
}
#Override
public Object intercept(Object arg0, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
Method m = findMethod(this.getClass(), method);
if (m != null) { return m.invoke(this, objects); }
Object res = method.invoke(realObj, objects);
return res;
}
private Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Here is Main and the results you get if you run it.
import net.sf.cglib.proxy.Enhancer;
public class Main {
private static MyClass unwrapped;
private static WrapperClass wrapped;
private static MyClass proxified;
public static void main(String[] args) {
unwrapped = new MyClass();
System.out.println(">>> Methods from the unwrapped object:");
unwrapped.method1();
unwrapped.method2();
unwrapped.method3();
wrapped = new WrapperClass(unwrapped);
System.out.println(">>> Methods from the wrapped object:");
wrapped.method1();
wrapped.method2();
wrapped.method3();
proxified = createProxy(unwrapped);
System.out.println(">>> Methods from the proxy object:");
proxified.method1();
proxified.method2();
proxified.method3();
}
#SuppressWarnings("unchecked")
public static <T> T createProxy(T obj) {
Enhancer e = new Enhancer();
e.setSuperclass(obj.getClass());
e.setCallback(new MyInterceptor(obj));
T proxifiedObj = (T) e.create();
return proxifiedObj;
}
}
>>> Methods from the unwrapped object:
This is method 1 - MyClass#e26db62
This is method 2 - MyClass#e26db62
This is method 3 - MyClass#e26db62
>>> Methods from the wrapped object:
This is method 1 - WrapperClass#7b7035c6
This is overridden method 2 - MyClass#e26db62
This is method 3 - WrapperClass#7b7035c6
>>> Methods from the proxy object:
This is method 1 - MyClass#e26db62
This is overridden method 2 - MyClass#e26db62
This is method 3 - MyClass#e26db62
As you can see, when you run the methods on wrapped you get the wrapper for the methods that are not overridden (i.e. method1() and method3()). When you run the methods on proxified, however, all of the methods are run on the wrapped object without the pain of having to delegate them all in WrapperClass or put all of the method signatures in an interface. Thanks to #CoronA and #Mark-Bramnik for what seems like a pretty cool solution to this problem.
Check the #Delegate annotation from Lombok framework:
https://projectlombok.org/features/Delegate.html
Switch to Groovy :-)
#CompileStatic
public class WrapperClass extends MyClass {
#Delegate private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
//Done. That's it.
}
http://mrhaki.blogspot.com/2009/08/groovy-goodness-delegate-to-simplify.html
You don't have to do this -- your Wrapper class is a subclass of the original class, so it inherits all of its publicly accessible methods -- and if you don't implement them, the original method will be called.
You shouldn't have extends Myclass together with a private MyClass object -- that's really really redundant, and I can't think of a design pattern where doing that is right. Your WrapperClass is a MyClass, and hence you can just use its own fields and methods instead of calling delegate.
EDIT: In the case of MyClass being final, you'd be circumventing the willfull declaration to not allow subclassing by "faking" inheritance; I can't think of anyone willing to do that other than you, who is in control of WrapperClass; but, since you're in control of WrapperClass, not wrapping everything you don't need is really more than an option -- it's the right thing to do, because your object is not a MyClass, and should only behave like one in the cases you mentally considered.
EDIT you've just changed your question to mean something completely different by removing the MyClass superclass to your WrapperClass; that's a bit bad, because it invalidates all answers given so far. You should have opened another question.
Credits go to CoronA for Pointing out the Proxy and InvocationHandler classes. I worked out a more reusable utility class based on his solution, using generics:
public class DelegationUtils {
public static <I> I wrap(Class<I> iface, I wrapped) {
return wrapInternally(iface, wrapped, new SimpleDecorator(wrapped));
}
private static <I> I wrapInternally (Class<I> iface, I wrapped, InvocationHandler handler) {
return (I) Proxy.newProxyInstance(wrapped.getClass().getClassLoader(), new Class[] { iface }, handler);
}
private static class SimpleDecorator<T> implements InvocationHandler {
private final T delegate;
private SimpleDecorator(T delegate) {
this.delegate = delegate;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = findMethod(delegate.getClass(), method);
if (m == null) {
throw new NullPointerException("Found no method " + method + " in delegate: " + delegate);
}
return m.invoke(delegate, args);
}
}
private static Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
Test it:
public class Test {
public interface Test {
public void sayHello ();
}
public static class TestImpl implements Test {
#Override
public void sayHello() {
System.out.println("HELLO!");
}
}
public static void main(String[] args) {
Test proxy = DelegationUtils.wrap(Test.class, new TestImpl());
proxy.sayHello();
}
}
I wanted to create an automatic delegation class that executes the delegatee's methods on the EDT. With this class, you just create a new utility method that will use an EDTDecorator, in which the implementation will wrap m.invoke in a SwingUtilities.invokeLater.
However, if I reflect on this, I may want to reconsider making a non-Reflection based proxy per interface that I have - it might be cleaner and faster, and more understandable. But, it's possible.
Define a method in WrapperClass i.e. delegate() that returns the instance of MyClass
OR
You can use reflection to do that but the caller has to pass the method name as an argument to an exposed method. And there will be complications regarding the method arguments/overloaded methods etc.
BTW: I can not use inheritance because the delegate is not under my control.I just get its instance from elsewhere (another case would be if MyClass was final)
The code that you have posted has public class WrapperClass extends MyClass
Actually your current implementation of WrapperClass is actually a decorator on top of MyClass
Let me redefine the problem for a specific case.
I want to override the close method of ResultSet interface in jdbc. My aim is to close the preparedstatement in close method of result set. I could not access to the Class (DelegatingResultSet) that implements in ResultSet interface. There are a lot of methods in ResultSet interface and overriding them one by one and calling the corresponding method from the ResultSet object is one solution. For a dynamic solution I used Dynamic ProxyClasses (https://docs.oracle.com/javase/1.5.0/docs/guide/reflection/proxy.html).
// New ResultSet implementation
public class MyResultSet implements InvocationHandler {
ResultSet rs;
PreparedStatement ps;
private Method closeMethod;
public MyResultSet(ResultSet rs, PreparedStatement ps) {
super();
this.rs = rs;
this.ps = ps;
try {
closeMethod = ResultSet.class.getMethod("close",null);
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
public void close() {
try {
rs.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Object newInstance(ResultSet rs, PreparedStatement ps) {
return java.lang.reflect.Proxy.newProxyInstance(rs.getClass().getClassLoader(), rs.getClass().getInterfaces(),
new MyResultSet(rs,ps));
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result = null;
try {
Class declaringClass = m.getDeclaringClass();
if (m.getName().compareTo("close")==0) {
close();
} else {
result = m.invoke(rs, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
}
return result;
}
}
// How to call it:
ResultSet prs = (ResultSet) MyResultSet.newInstance(rs,ps);
I really appreciated #CoronA's answer. I also looked at #Mark Cramer's answer, but, if I'm not missing something, I think that there are always at least two instances of the "proxified" class with a strange relationship beteen the two objects.
This, along with the fact that cglib is now deprecated, pushed me to find a new implementation based on ByteBuddy.
This is what I came up with:
public class MyClass {
public String testMethod() {
return "11111";
}
public String testMethod2() {
return "aaaaa";
}
}
public class MyClassWithDelegate extends MyClass {
private static final Constructor<? extends MyClassWithDelegate> CONSTRUCTOR_WITH_DELEGATE;
static {
Constructor<? extends MyClassWithDelegate> temp = null;
try {
final var instrumentedMyClassWithDelegateType =
new ByteBuddy()
.subclass(MyClassWithDelegate.class)
.method(ElementMatchers.any())
.intercept(MethodDelegation.to(MethodInterceptor.class))
.make()
.load(MyClassWithDelegate.class.getClassLoader())
.getLoaded();
temp = instrumentedMyClassWithDelegateType.getConstructor(MyClass.class);
} catch (final Exception e) {
LOGGER.error("Cannot instrument class {}", MyClassWithDelegate.class, e);
}
CONSTRUCTOR_WITH_DELEGATE = temp;
}
public static MyClassWithDelegate getInstanceWithDelegate(final MyClass myClass) {
try {
return CONSTRUCTOR_WITH_DELEGATE.newInstance(myClass);
} catch (final Exception e) {
LOGGER.error("Cannot get instance of {}", MyClassWithDelegate.class, e);
throw new IllegalStateException();
}
}
private final boolean initialized;
private final MyClass delegate;
public MyClassWithDelegate(final MyClass delegate) {
super();
this.delegate = delegate;
this.initialized = true;
}
public String testMethod() {
return "22222";
}
public static class MethodInterceptor {
#RuntimeType
public static Object intercept(#This final MyClassWithDelegate self,
#Origin final Method method,
#AllArguments final Object[] args,
#SuperMethod final Method superMethod) throws Throwable {
if (!self.initialized || method.getDeclaringClass().equals(MyClassWithDelegate.class)) {
return superMethod.invoke(self, args);
} else {
return method.invoke(self.delegate, args);
}
}
}
}
The initialized field is used to prevent method calls the super constructor from being redirected to the delegate before its assignment (in this case it wouldn't be a problem, but I wanted to create a generic solution).
Every method called on an instance of MyClassWithDelegate will be redirected to the delegate, except from methods declared inside MyClassWithDelegate itself.
In this example, calling testMethod() on an instance of MyClassWithDelegate will return "22222", while testMethod2() will return "aaaaa".
Obviously, the delegation will actually work only if every instance of MyClassWithDelegate is obtained calling the getInstanceWithDelegate factory method.

How can I access a method of an "unnamed" class?

public class Test {
public static void main(String[] args) {
DemoAbstractClass abstractClass = new DemoAbstractClass() {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
};
abstractClass.runner();
/**
* I want to access getVal method here
*/
}
}
abstract class DemoAbstractClass {
public void run() {
System.out.println("running");
}
public abstract void runner();
}
Here, I'm declaring an abstract class DemoAbstractClass. I can obviously create a new class that extends this class and add this method to it. But, I would prefer not doing that in my scenario.
Is there any other way to access getVal method in above code??
You can't. You need to make a proper (non-anomous) class out of it. Make it an inner private class if you want to limit its scope.
Alternatively, you could use a StringBuffer and share a referense to it between the methods. Not extremely clean however.
Related question:
Accessing inner anonymous class members
Short of using reflection, you cannot as you have no access to the concrete type of the object to be able to bind the methodcall to
If you don want to do something like this in a sane manner, declare a named class and use that as the type of abstractClass
Unfortunately, if you cannot name the type, you cannot access the methods at the language level.
What you can do, though, is use the reflection API to get a Method object and invoke it on this object.
This, however, is pretty slow. A private class or private interface would be much faster.
I can obviously create a new class that extends this class and add this method to it.
You've already done this; the end result was an anonymous inner class: new DemoAbstractClass() { ... }; If you just moved that declaration into its own class -- you can even make it a private class -- you can access getVal.
Per your example above:
public class Test {
public static void main(String[] args) {
DemoClass abstractClass = new DemoClass();
abstractClass.runner();
/**
* I want to access getVal method here
*/
abstractClass.getVal(); // can do this here now
}
private class DemoClass extends DemoAbstractClass {
private String val;
#Override
public void runner() {
val = "test";
System.out.println(val);
this.run();
}
public String getVal() {
return val;
}
}
}
}
Another option is to make a StringBuilder a member of the main method and use the closure nature of anonymous inner methods:
public static void main(String[] args) {
final StringBuilder value = new StringBuilder();
DemoAbstractClass abstractClass = new DemoAbstractClass() {
#Override
public void runner() {
value.append( "test" );
System.out.println(val);
this.run();
}
};
abstractClass.runner();
// use val here...
String val = value.toString();
}

Categories