2010-06-29 55 views
3

我在使用NetBeans模塊應用程序中的java ServiceLoader時遇到麻煩。這是我想要做的(並且它在Eclipse中的普通Java應用程序中工作):如何使java ServiceLoader在NetBeans 6.9模塊應用程序中工作

我有一個interface.jar,它聲明瞭接口。我有implements.jar,它有幾個這個接口的實現,都在spi/META-INF/services/my.package.name.MyInteface文件中指定(這個文件在實現.jar中)。

我也有類ImplementationHandler(在又一handler.jar),其具有以下的方法來加載所有實現:

private static List<MyInterface<?>> loadAllImplementations() { 
    List<MyInterface<?>> foundImplementations = Lists.newArrayList(); 
    try { 
     for (MyInterface implementation : ServiceLoader.load(MyInterface.class)) { 
      foundImplementations.add(implementation); 
     } 
    } catch (ServiceConfigurationError error) { 
     system.out.println("Exception happened"); 
    } 
    return foundImplementations; 
} 

此代碼返回在Eclipse正常應用的所有實現(該foundImplementations.size ()> 0)。

但是在NetBeans下,它找不到任何東西(foundImplementations.size()== 0)。

更多細節:
我有一個NetBeans模塊的應用程序(開源的,不是我寫的),我需要通過一些MyInterface的實現延長的來源。 interface.jar,implements.jar和handler.jar是在Eclipse中創建的,它們是另一個應用程序的一部分。

在NetBeans中,我打開了需要使用新圖案的模塊,並將所有3個罐子都添加爲外部庫(NetBeans將它們複製到它的ext文件夾中,我不想但我不能做任何關於 - 我想他們在另一個myext文件夾中,但這是另一個故事)。然後我重建一切,並試圖用我的實現方式之一,但它沒有被發現......這得到實現的代碼是在ImplementationHandler類,看起來像:

public static final <T> MyInteface<T> getByName(String name) { 
    for (MyInteface implementation : loadAllImplementations()) { 
     if (implementation.getName().equals(name)) { 
      return implementation; 
     } 
    } 

    throw new IllegalArgumentException("Unable to find MyInterface class for: " + name); 
} 

我得到了我的異常「無法找到MyInteface類爲:myImplementationName「...

我對NetBeans的知識非常有限,我想知道是否還有更多的事情需要我去做,以實現這個目標?

+0

'spi/META-INF/services /'中的'spi'是否爲錯字? META-INF文件夾應位於類路徑的根目錄中。 – 2010-07-02 15:01:12

+0

是的,對不起,我粘貼了從構建腳本中獲取文件的「源」路徑。它在罐子的根部,我檢查過。如果它不在那裏,它不應該在Eclipse中工作:) – 2010-07-05 14:59:58

回答

0

我放棄了,用JSPF替換ClassLoader。這可以直接使用,我不需要了解第三方程序的內部結構,這些程序是作爲NetBeans模塊編寫的,以及它如何影響給類加載器的類路徑。

0

ServiceLoader.load(Class)使用當前線程的上下文類加載器來加載所有的實現。這可能是,你的情況你的jar文件(implementation.jar)中的實現類不在該類加載器的類路徑中。

你可能要爲此嘗試不同的方法:

  • 您可能要麼必須在NetBeans模塊的類路徑中所有的罐子或
  • 您可能需要創建一個類加載器(可能是URLClassLoader在類路徑中包含這些jar)並使用ServiceLoader.load(Class, ClassLoader)並傳遞該類加載器。
  • 還有另一個選項可以嘗試,但我不確定:jar文件規範允許您指定Class-Path清單屬性,您可以在其中添加'implementation.jar'條目。更多詳細信息here

很可能,handler.jar和implements.jar不會由同一個類加載器加載。你也可能想看看爲什麼你的文件到達ext文件夾。

希望這會有所幫助。

編輯:

  • 也可以嘗試調用它使用系統類加載器(即啓動應用程序的一個)ServiceLoader.load(Class, null)。可能該類加載器可能能夠在位於ext目錄中的jar中找到類。
+0

嗨,感謝您的答案!我將首先嚐試System類加載器。這些jar應該位於netbeans模塊類路徑中,因爲我將它們作爲庫添加到將使用它們的模塊中,而不是添加到整個項目中。我認爲這是默認情況下,你的罐子然後進入ext文件夾,我不認爲這很重要,因爲netbeans自動生成這個類路徑清單屬性,你描述。我檢查了這個屬性,它正確地指向了ext文件夾中的所有罐子,罐子在那裏。 – 2010-07-05 07:38:33

+0

系統類加載器也沒有看到它們:( – 2010-07-05 14:06:14

+0

可能@JörnHorstmann的評論可能對spi目錄有一些線索嗎?METAR-INF目錄是jar根目錄? 最後的手段是嘗試使用URLClassLoader方法 – naikus 2010-07-05 14:44:23

2

爲了工作,你必須讓Netbeans在META-INF中創建這個服務子文件夾。這很容易做到,但信息很容易獲得。

要添加一些東西到META-INF,您需要在src /(源目錄[spi?])文件夾中創建一個名稱的文件夾。在這種情況下,您還需要services文件夾,並在其中創建一個與您的服務界面具有相同完全限定名稱的文本文件。最後你應該有這樣的結構:src/META-INF/services/my.package.MyInterface。

最後,這個[my.package.MyInterface]文件的內容應該列出所有實現類(每行一個)。

使用此設置,Netbeans將在構建應用程序時創建適當的jar。

看一看this ServiceLoader的例子。這是一個完整的例子,儘管它沒有解釋我剛剛描述的Netbeans集成。

相關問題