2010-06-29 4 views
3

NetBeans 모듈 응용 프로그램에서 java ServiceLoader를 사용하는 데 문제가 있습니다. 여기에 내가 뭘 하려는지 (그리고 그것은 Eclipse에서 정상적인 자바 응용 프로그램에서 작동합니다) :NetBeans 6.9 모듈 응용 프로그램에서 java ServiceLoader를 만드는 방법

나는 인터페이스를 선언하는 interface.jar 있습니다. 그리고이 인터페이스의 구현이 여러 개있는 implementations.jar가 있습니다. 모두 spi/META-INF/services/my.package.name.MyInteface 파일에 지정되어 있습니다 (이 파일은 implemenations.jar에 있음).

나는 또한 모든 구현로드하기 위해 다음과 같은 방법이있는 클래스 ImplementationHandler (또 다른 handler.jar에서)를 가지고

:합니다 (foundImplementations.size을

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; 
} 

이 코드는 이클립스 일반 응용 프로그램의 모든 구현을 반환합니다()> 0).

그러나 NetBeans에서는 (foundImplementations.size() == 0) 아무것도 찾을 수 없습니다.

자세한 내용은 :
내가하는 MyInterface 구현의 일부를 사용하여 확장 할 필요가 넷빈즈 모듈 응용 프로그램 (내게로 작성되지 않은 오픈 소스)의 소스를 가지고있다. interface.jar, implementations.jar 및 handler.jar은 Eclipse에서 작성되며 다른 응용 프로그램의 일부입니다.

NetBeans에서 새로운 impplementations를 사용해야하는 모듈을 열었고 모든 3 개의 jar 파일을 외부 라이브러리로 추가했습니다 (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); 
} 

"할 수 없습니다 MyImplayerName에 대한 MyInteface 클래스 찾기 ...

NetBeans에 대한 지식이 매우 부족하며이 기능을 사용하려면 더 많은 작업이 필요합니까?

+0

'spi/META-INF/services /'의 'spi'가 오타입니까? META-INF 폴더는 클래스 경로의 루트 디렉토리에 있어야합니다. –

+0

예, 죄송합니다. 파일을 빌드 스크립트에서 가져온 "소스"경로를 붙여 넣었습니다. 항아리의 뿌리에 들어갑니다. 만약 거기에 없었다면, 그것도 일식에서 일한해서는 안됩니다 :) –

답변

0

포기하고 ClassLoader를 JSPF으로 바꿨습니다. 이것은 기본적으로 작동하며 NetBeans 모듈로 작성된 써드 파티 프로그램의 내부 구조와 클래스 로더에 주어진 클래스 경로에 미치는 영향에 대해 알 필요가 없습니다.

0

ServiceLoader.load (Class)는 현재 스레드의 컨텍스트 클래스 로더를 사용하여 모든 구현을로드합니다. 귀하의 경우에 jar 파일 (implementation.jar)의 구현 클래스가 해당 클래스 로더의 클래스 경로에 있지 않을 수도 있습니다.

이 서로 다른 접근 방법을 시도 할 수 있습니다 : 당신은 클래스 로더를 작성해야 할 수도 있습니다

    • 당신은 모든 넷빈즈 모듈의 클래스 경로에 항아리 또는이 필요 수도 있고, (아마를 URLClassLoader 클래스 패스에 해당 항아리가 있음). ServiceLoader.load(Class, ClassLoader)을 사용하고 해당 클래스 로더를 전달하십시오.
    • 시도 할 수있는 또 다른 옵션이 있지만 잘 모르겠습니다. jar 파일 스펙을 사용하면 'implementation.jar'항목을 추가 할 수있는 클래스 경로 매니페스트 특성을 지정할 수 있습니다. 세부 정보 here

    대부분의 경우 handler.jar 및 implementations.jar은 동일한 클래스 로더에 의해로드되지 않습니다. 또한 파일을 ext 폴더로 가져 오는 이유에 대해 살펴볼 수도 있습니다.

    희망이 도움이됩니다.

    편집 :

    • 또한 시스템 클래스 로더 (응용 프로그램을 시작 하나)를 사용하는 ServiceLoader.load(Class, null)를 호출하려고합니다. 아마도 클래스 로더는 ext 디렉토리에있는 jar 파일을 찾을 수있을 것입니다.
  • +0

    안녕, 대답 주셔서 감사합니다! 먼저 System 클래스 로더를 사용해 보겠습니다. jar 파일은 netbeans 모듈 클래스 경로에 있어야합니다. 라이브러리로 모듈을 추가하기 때문에 전체 프로젝트가 아닌 모듈을 사용할 것입니다. 귀하의 항아리가 ext 폴더에 들어가서 기본적으로 그렇게 생각하지 않는다고 생각합니다. netbeans가이 Class-Path manifest 속성을 자동으로 생성했기 때문에 당신이 설명했습니다. 나는이 속성을 체크했는데 ext 폴더의 모든 jar를 정확하게 가리키며 jar 파일이 있습니다. –

    +0

    시스템 클래스 로더가 그것들을 보지 못한다 : ( –

    +0

    @ Jörn Horstmann의 코멘트가 spi 디렉토리에 관한 단서가있을 수 있는가? META-INF 디렉토리가 jar의 루트에 있는가 최후의 수단은 URLClassLoader 접근 방식을 시도하고있다. – naikus

    2

    작동하려면 넷빈즈가 META-INF 내부에이 서비스 하위 폴더를 만들어야합니다. 매우 쉽게 할 수 있지만 정보에 쉽게 액세스 할 수 있습니다.

    META-INF에 항목을 추가하려면 src/(원본 디렉토리 [spi?]) 폴더에이 이름의 폴더를 만들어야합니다. 이 경우 서비스 폴더가 필요하고 서비스 폴더와 동일한 정규화 된 이름의 텍스트 파일을 만듭니다. 결국 src/META-INF/services/my.package.MyInterface와 같은 구조를 가져야한다.

    마지막으로이 [my.package.MyInterface] 파일의 내용에는 모든 구현 클래스가 한 줄에 하나씩 나열되어야합니다.

    이 설정으로 Netbeans은 앱을 만들 때 적절한 jar를 만듭니다.

    예를 들어 this ServiceLoader을보십시오. 방금 설명한 Netbeans 통합을 설명하지는 않지만 완전한 예제입니다.

    관련 문제