-
-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
default
interface methods. Or not.
#240
Comments
Can you create a example demonstrating this? I would like to understand where the "default" implementation comes from... |
That is what is strange, because I haven't provided one. I'll get together a self contained example. |
package com.acme;
import org.freedesktop.dbus.connections.impl.DBusConnection;
import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder;
import org.freedesktop.dbus.interfaces.DBusInterface;
public class DefaultInterfaceMethodTest {
public final static void main(String[] args) throws Exception {
try (DBusConnection conn = DBusConnectionBuilder.forSessionBus().withShared(false).build()) {
DBusAPI obj = new DBusAPIImpl();
conn.requestBusName("com.acme");
conn.exportObject(obj);
Thread.sleep(Integer.MAX_VALUE);
}
}
/* The following two interface in the real world exist in a separate
* library that does not link to dbus in any way
*/
public interface RootItem {
}
public interface Root<ITEM_TYPE extends RootItem> {
ITEM_TYPE getItem(long itemId);
}
/* And the remaining 2 interfaces and 1 class here are dbus specific
* implementations of the above
*/
public interface DBusItem extends RootItem, DBusInterface {
}
public interface DBusAPI extends Root<DBusItem>, DBusInterface {
@Override
DBusItem getItem(long itemId);
}
public static class DBusAPIImpl implements DBusAPI {
@Override
public DBusItem getItem(long itemId) {
/// do stuff to get item
return new DBusItem() {
@Override
public String getObjectPath() {
return "/com/acme/Items/" + itemId;
}
};
}
@Override
public String getObjectPath() {
return "/com/acme/MyApi";
}
@Override
public boolean isRemote() {
return true;
}
}
} If you put a
As you can see, there are no |
So after digging into this, I guess you stumbled across a bridging method generated by the compiler. Those methods will be created when multiple methods will override one another from the language perspective. So we got three things which needs to be taken care of: default implementations in interfaces, synthetic methods and bridge methods. I think the
|
Ohh interesting. Today I learned something new about Java :) All the above makes sense. One further thing ... I was thinking about |
Me too. Most of the time one does not really care what is happening under the hood.. but in some rare cases these details make the difference.
I'm really not so sure what's the best way to deal with default methods. |
Heh yeh, I'm thinking they may be useful for something like this this .. public interface SomeExternalDBusService extends DBusInterface {
@DBusBoundProperty
long getMemoryUsed();
@DBusBoundProperty
long getMemoryTotal();
/* SomeService doesn't provide us with a getMemoryFree(), so we make our own as a convenience to you */
default long getMemoryFree() {
return getMemoryTotal() - getMemoryUsed();
}
} I'm pretty sure it's no more than a handful of lines of code in |
I have a situation where I am sharing some code across a few modules, and my
DBusInterface
interface and implementation extend a generic interface that is used outside of the dbus components.Something like this ..
This will fail to export the interface.
What appears to be happening, is that the
getItem()
method is being found twice. What is is interesting, is that one occurrence is being identified as adefault
method even though it's not, while the other is being identified asabstract
(like all the other methods in the interface that do not have this generic type).Doing a
System.out
of the two methods that are found results in ...I could fix this by adding a
@DBusIgnore
toRoot
, butRoot
is in a module that does not havedbus-java
on the CLASSPATH.So instead, I changed
dbus-java
sExportedObject.isExcluded()
method.And now it all works again.
This doesn't seem to have any other ill effects to the DBus API. Everything else is still getting exported correctly. It seems that it is only identified as
default
with this particular arrangement of interfaces, OR if you do actually use adefault
method in theDBusInterface
.I think this may be a valid fix, because using a
default
method doesn't make sense anyway. If you are acting as a client, accessing an external DBus service from Java, then default methods don't work anyway (RemoteInvocationHandler
tries to run it as if it were a remote method). It might be valid if you are exporting an API from Java, but then you cannot share those interface definitions with client code.TLDR; I think
default
methods in DBus interfaces should be excluded by defaultThe text was updated successfully, but these errors were encountered: