Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create an exception-safe wrapper of a class

Tags:

java

exception

I have a legacy class C1, implementing interface I, that may throw some exceptions.

I want to create a class C2, also implementing interface I, that is based on an instance of C1, but catches all exceptions and does something useful about them.

Currently my implementation looks like this:

class C2 implements I {
    C1 base;

    @Override void func1() {
      try {
         base.func1();
      } catch (Exception e) {
         doSomething(e);
      }
    }

    @Override void func2() {
      try {
         base.func2();
      } catch (Exception e) {
         doSomething(e);
      }
    }

    ...

}

(Note: I could also make C2 extend C1. This does not matter for the current question).

The interface contains many functions, so I have to write the same try... catch block again and again.

Is there a way to reduce the amount of code duplication here?

like image 677
Erel Segal-Halevi Avatar asked May 06 '13 05:05

Erel Segal-Halevi


1 Answers

You can make a Proxy, it could actually be generic

interface I1 {
    void test();
}

class C1 implements I1 {
    public void test() {
        System.out.println("test");
        throw new RuntimeException();
    }
}

class ExceptionHandler implements InvocationHandler {
    Object obj;

    ExceptionHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return method.invoke(obj, args);
        } catch (Exception e) {
            // need a workaround for primitive return types
            return null;
        }
    }

    static <T> T proxyFor(Object obj, Class<T> i) {
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), new Class[] { i },
                new ExceptionHandler(obj));
    }
}

public class Test2 {

    public static void main(String[] args) throws Exception {
        I1 i1 = ExceptionHandler.proxyFor(new C1(), I1.class);
        i1.test();
    }
}
like image 149
Evgeniy Dorofeev Avatar answered Oct 04 '22 22:10

Evgeniy Dorofeev