2015-08-27 38 views
1

背景NoSuchMethodException - 方法的返回類型已經改變 - 要接受這兩種類型

我有一個公共圖書館,我需要更新。這個公共庫有一個第三方依賴項(jgroups),它在新版本中發生了顯着變化。通過傳遞依賴關係,有時需要更新版本的jgroups,這會打破公共庫。我需要更新一些類以與新版本兼容,同時保持向後兼容性。

的問題

的JGroups提供View類,它有一個方法getMembers()。在舊版本(2.10.0)中,此方法返回Vector<Address>,而在較新版本(3.2.7)中,返回List<Address>。任何java.util.Collection的實施都適用於我,但問題是我得到NoSuchMethodException。據我所知,getMembers()找到的方法具有傳統的Vector<Address>返回類型(基於commons庫中的JGroups依賴項),但我拖入新的JGroups版本,View類預計從getMembers()方法返回的List<Address>

堆棧跟蹤

我開始了我在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] 
.... 

當它打破

Collection<Address> viewMembers = view.getMembers(); 

問題

是否可以支持兩個版本,即使它們的Collection不同的實現?我如何處理這種情況,直到運行時我才知道方法的返回類型?

注:

我曾試圖排除JGroups的舊版本正在由我的Maven POM文件添加排除拉入。這沒有奏效。

<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> 
+1

更多的解決方法的黑客解決方法 - 但如何提供自己的實用工具方法,並調用'getMembersRaw()'來代替。這將返回底層數組 - 因此您需要將這些值複製到集合中以防止意外修改。 http://www.jgroups.org/javadoc/org/jgroups/View.html#getMembersRaw-- – deyur

+0

@deyur,感謝您的建議。不幸的是,getMembersRaw()在我的JGroups版本中不可用,2.10.0或3.2.7 –

+1

如何使用反射? Field View.members是2.10.x中的Vector

和3.x中的Address []數組。您可以訪問字段View.members,並根據其類型返回所有​​成員作爲地址集合。不好,但應該工作... –

回答

1

如何使用反射? Field View.members是2.10.x中的Vector和3.x中的Address []數組。您可以訪問字段View.members,並根據其類型返回所有​​成員作爲地址集合。不是很好,但應該工作..

1

如果您在應用程序框架中使用「普通Java」,我認爲您一般不走運。

不使用某種模塊框架(如OSGI),只有一個類的池,每個加載到類路徑中的類都會進入該池。這意味着您不能同時在JVM中擁有同一個JAR或同一個類的多個版本。

而且,你必須支持相同的JAR的多個版本,因爲你的代碼中至少兩片編譯每對不同的版本:一個是預期的Vector返回值和其他的List,所以即使你可以從構建環境中隔離不需要的人,那麼針對它構建的代碼將不會鏈接到正確的二進制文件,並且您將繼續獲得您所看到的運行時異常。

不幸的是,您提到這是一個「庫」,而不是一個單一的應用程序,這可能使應用解決方案變得更加困難。關閉我的頭頂,我看到這些選項,你往前走,沒有一個是微不足道的,有些可能是不可能的:

  1. 降級您的代碼所必需的只有JGroups的一個版本中的所有依賴鏈
  2. 重新構建您的應用程序使用OSGI或支持同一個庫的多個版本,所以依賴鏈可以發散
  3. 重新構建您的應用程序,它分裂成多個,在自己的JVM每次運行時,與插座或通信的類似框架任何其他方式

例如,我們已經使用第三種方法分割了應用程序的一小部分,因此它可能依賴於許可證庫對我們的整個代碼庫不友好,但該部分可能會與庫一起獲得許可。

我也不確定Java 9模塊系統如何處理這個問題,但它可能同時支持同一模塊的多個版本。如果您可以選擇使用該測試版或進行調查,那可能值得您付出努力。但是,您提到這一點是向後兼容性的,因此這可能不是一個可行的選項。