Welcome! Please see the About page for a little more info on how this works.

+4 votes
in Clojure by
edited by

Given an interface

public interface Foo {
    void bar(Object o);

And a proxy over that interface:

(proxy [Foo] []
  (bar [o] (baz o)))

When the interface gets updated to

public interface Foo {
  void bar(Object o);

  // java 8 default method, quote from 
  // https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
  // "Default methods enable you to add new functionality to the
  // interfaces of your libraries and ensure binary compatibility
  // with code written for older versions of those interfaces."
  default void bar(Object o, Object p) {

Calls to instanceCreatedByProxy.bar(o, p) will not work as it could be expected.

reify is not affected by this.

Repro repo: https://github.com/imrekoszo/proxy-default

There is no indication of this behavior in the docstring of proxy, the only reference I saw to this is an example on clojuredocs.

This is troublesome as it might prevent an otherwise non-breaking library upgrade. If the code calling proxy is under one's control they could use reify instead (especially as this is recommended in the official docs). However if it is in an external library this is not a viable workaround.

Is this a bug or a known limitation of proxy?
If the latter, then could this perhaps be made more visible, for example through a warning in the docstring?

- link to original slack thread
- added link to reify recommendation

2 Answers

0 votes
selected by
Thank you Alex.

I updated the repro repo to try and answer Ghadi Shayban's question there but I seem to be unable to comment on the issue.

It appears this also breaks when other default methods are added to the interface: https://github.com/imrekoszo/proxy-default/commit/6a2ddd2a5febdadc85adfb44957c0f010ebe7419