Background
I have a commons library that I have to update. This commons library has a third party dependency (jgroups) which was changed significantly in newer versions. Through transitive dependencies, the newer version of jgroups is sometimes required and this breaks the commons library. I need to update some classes for compatibility with newer versions, while maintaining backwards compatibility.
The Problem
JGroups provides a View
class, which has a method getMembers()
. In the old version (2.10.0), this method returns Vector<Address>
and in the newer version (3.2.7), this returns List<Address>
. Any implementation of java.util.Collection
will work for me, but the problem is I'm getting a NoSuchMethodException
. As I understand it, the getMembers()
method found has the legacy Vector<Address>
return type (based on the JGroups dependency in the commons library), but I am dragging in a newer JGroups version and that View
class expects a List<Address>
returned from the getMembers()
method.
Stacktrace
I get the following error when starting up my application in Eclipse.
Caused by: java.lang.NoSuchMethodError: org.jgroups.View.getMembers()Ljava/util/Vector;
at com.mycompany.commons.messaging.events.impl.distributed.JGroupsEventDistributionProvider$JGroupsEventReceiver.viewAccepted(JGroupsEventDistributionProvider.java:136) ~[classes/:na]
at org.jgroups.JChannel.invokeCallback(JChannel.java:752) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
at org.jgroups.JChannel.up(JChannel.java:710) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
at org.jgroups.stack.ProtocolStack.up(ProtocolStack.java:1020) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
at org.jgroups.protocols.pbcast.FLUSH.up(FLUSH.java:466) ~[jgroups-3.2.7.Final.jar:3.2.7.Final]
....
Where it breaks
Collection<Address> viewMembers = view.getMembers();
Question
Is it possible to support both versions, even though they are different implementations of Collection
? How can I handle this scenario where I don't know the method return type until runtime?
Note:
I have tried to exclude the older version of JGroups that is being pulled in by adding an exclusion in my maven pom. This has not worked.
<dependency>
<groupId>com.mycompany.commons</groupId>
<artifactId>mycompany-commons-event-distributed-jgroups</artifactId>
<!-- Note: JGroups dependency is provided by infinispan -->
<version>1.0.2-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
</exclusion>
</exclusions>
</dependency>
How about using reflection ? Field View.members is a Vector in 2.10.x and an Address[] array in 3.x. You could access field View.members and - depending on its type - return all members as a collection of addresses. Not nice, but should work..