Contents

Duck Typing for Java

Contents

Every now and then I need to implement some interface, but only one (or very few) methods of it. Usually I need something like this in test code, but it is useful elsewhere, too. The mocking libraries I have seen so far offer something similar, but not quite in the way I want to have it.

I had the idea to use something like duck typing for it for a while now. Yesterday I finally found some time to implement it. So I present to you duckprxy. You give it an interface to implement and an object to delegate to you and duckprxy will call the delegate according to the name of the method.

The service interface for this service is defined by DuckProxy. Currently there are two different implementations, but more on that later. Let us assume that the field duckProxy holds such an implementation of DuckProxy (e.g., via injection). Then we can do the following:

interface MyInterface {
    void foo();
    int bar(int x, int y);
}
public class Delegate {
    public int bar() { return 42; }
}
...
MyInterface prxy = duckProxy.makeProxy(MyInterface.class, new Delegate());
prxy.bar(2, 3); // Will return 42.

The standard behavior if an unimplemented method is called is to throw an exception. However, the delegate class can specify a fallback method to call.

public class Delegate {
    ...
    @DuckMethod(fallback = true)
    public int defaultMethod(
            @DuckArg(DuckArgType.NAME) String name) {
        log.info("called method " + name);
    }
}

Now every time an unspecified method is called, it will simply be logged.

Other features:

  • Mapping calls to methods with patterns.
  • Defining sub-delegates to allow easy overriding of a few methods, while the rest is handled by the sub-delegate.

Right now you need to define a class to use the extra-features with annotations. But I am thinking about also allowing to annotate the delegate variable instead of the delegate class.

As mentioned before, there are currently two implementations of DuckProxy. The first is DuckPrxyImpl. This one basically looks what method to call when the call actually happens. The second is DuckPrxyPreCompImpl. This one pre-computes the mapping of the methods in the given interface to the delegate.

I am thinking about using something like javassist for a third implementation that creates a class instead of a proxy. This way the performance impact should be negligible.