OSGi 시작하기 5 – 서비스 사용하기 : [번역] Consuming a Service

이 글은 Neil Bartlett 의 연재 글 “Getting started with OSGi”의 번역본입니다.
* 파트 1 – 첫번째 번들 : Your First Bundle
* 파트 2 – 프레임워크와 연동하기 : Interacting with the Framework
* 파트 3 – 번들간의 의존관계 : Dependencies between bundles
* 파트 4 – 서비스 등록하기 : Registering a Service
에 이어 5번째 글입니다. 오탈자 및 이상한 번역은 댓글로 남겨주세요

Getting started with OSGi : OSGi 시작하기 파트 5 – 서비스 사용하기

저자 : Neil Bartlett < njbartlett at gmail dot com >
역자 : 권 정혁 < guruguru at gmail dot com >

글원본 : http://www.eclipsezone.com/eclipse/forums/t90796.html – Getting started with OSGi : Consuming a Service

마지막 글에서 우린 어떻게 서비스를 등록하는지에 대해 알아봤습니다. 이제 그 서비스를 찾고 다른 번들에서 그 서비스를 이용하도록 작업해 봅시다.

Martin Folwer의 Dependency Injection에 대한 글에서 영감을 얻었던 지난번처럼, 우린 문제를 우리 요구사항에 포함할 것입니니다. 우린 MovieFinder 를 서비스로 만들어서 서비스 레지스트리에 등록했습니다. 이젠 특정 감독에 의해 제작된 영화를 찾기위해 MovieFinder 를 사용하는 MovieLister를 만들어볼 것입니다. 그리고 이 MovieLister 자체도 GUI Application 같은 다른 특정번들에 사용되는 서비스가 될것이라고 가정합니다. 여기서 문제점은, OSGi 서비스는 동적이라 등록되고 사라지고 한다는것입니다. 즉, 우리가 MovieFinder 서비스를 호출하고자 할때, 서비스가 불가능할수도 있습니다.

그러면, 만약 MovieFinder 서비스가 존재하지 않는다면 MovieLister 는 무엇을 해야할까요 ? MovieLister 가 하는 일중에 MovieFinder 에 대한 호출이 매우 중요한 것이라는것은 확실하므로, 우리가 선택할수 있는 옵션은 몇가지 밖에 없습니다.

  1. 에러를 낸다. (Null 을 리턴하거나 Exception 을 내거나)
  2. 기다린다.
  3. 처음부터 아예 설치가 안되도록 한다. ( Don’t be there in the first place )

이 글에선 쉬운 앞에 2가지 방법만을 살펴보도록 합니다. 세번째 방법은 아직 여러분께 어떤 의미가 있게 보이진 않겠지만, 앞에 2가지를 보고나면 알수 있게 되실겁니다.

첫번째로 할일은 MovieLister 서비스에 대한 인터페이스를 작성하는것입니다. 아래 소스를 osgitut/movies/MovieLister.java 에 복사하세요.

package osgitut.movies;
import java.util.List;
public interface MovieLister {
    List listByDirector(String name);
}

이제 osgitut/movies/impl/MovieListerImpl.java 파일을 생성합니다.

package osgitut.movies.impl;
import java.util.*;
import osgitut.movies.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
public class MovieListerImpl implements MovieLister {
    private final ServiceTracker finderTrack;
    public MovieListerImpl(ServiceTracker finderTrack) {
        this.finderTrack = finderTrack;
    }
    public List listByDirector(String name) {
        MovieFinder finder = (MovieFinder) finderTrack.getService();
        if(finder == null) {
            return null;
        } else {
            return doSearch(name, finder);
        }
    }
    private List doSearch(String name, MovieFinder finder) {
        Movie[] movies = finder.findAll();
        List result = new LinkedList();
        for (int i = 0; i < movies.length; i++) {
            if(movies[i].getDirector().indexOf(name) > -1) {
                result.add(movies[i]);
            }
        }
        return result;
    }
}

이것이 아마 지금까지 샘플중 가장 긴 코드일겁니다! 그럼, 여기선 무슨일이 일어나고 있을까요 ? 첫번째로 실제 영화를 찾는 로직이 doSearch(String,MovieFinder) 메소드로 분리되어, OSGi 에 관련된 코드를 독립시키도록 도와주고 있습니다. 불가피 하게도, 우리가 검색을 하는 방법이 멍청하고 비효율적이지만, 그건 이 튜토리얼에는 크게 종요하지 않습니다. 어차피 우리 데이터베이스에는 딱! 2개의 영화만 있으니까요.

흥미로운건 서비스 레지스트리로부터 MovieFinder 를 찾기위해 ServiceTracker를 사용하는 listByDirector(String name) 메소드 입니다. ServiceTracker 는 OSGi API 의 재미없는 하위레벨 코드를 추상화시켜주는 매우 유용한 클래스입니다. 어쨋거나, 우린 정말 서비스가 존재하는지 체크할 필요가 있습니다. ServiceTracker 는 생성자로 전달되었다고 가정합니다.

여러분께선 아마도 ServiceTracker 를 사용하지 않고 레지스트리에서 서비스를 가져오는 코드를 보셨을수도 있습니다. 예를 들어 BundleContextgetServiceReferecegetService 를 호출하는것이 가능합니다. 하지만 이런 코드는 꽤 복잡하고 사용후 잘 지우도록 조심해야 합니다. 제 의견으론, 로우레벨 API를 사용하는 것의 이점은 매우 작고 많은 문제가 있습니다. ServiceTracker 를 항상 사용하는것이 좋습니다.

ServiceTracker 를 생성하기에 좋은곳은 bundle activator 입니다. 아래 코드를 osgitut/movies/impl/MovieListerActivator.java 에 복사하세요.

package osgitut.movies.impl;
import java.util.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
import osgitut.movies.*;
public class MovieListerActivator implements BundleActivator {
    private ServiceTracker finderTracker;
    private ServiceRegistration listerReg;
    public void start(BundleContext context) throws Exception {
        // Create and open the MovieFinder ServiceTracker
        finderTracker = new ServiceTracker(context, MovieFinder.class.getName(), null);
        finderTracker.open();
        // Create the MovieLister and register as a service
        MovieLister lister = new MovieListerImpl(finderTracker);
        listerReg = context.registerService(MovieLister.class.getName(), lister, null);
        // Execute the sample search
        doSampleSearch(lister);
    }
    public void stop(BundleContext context) throws Exception {
        // Unregister the MovieLister service
        listerReg.unregister();
        // Close the MovieFinder ServiceTracker
        finderTracker.close();
    }
    private void doSampleSearch(MovieLister lister) {
        List movies = lister.listByDirector("Miyazaki");
        if(movies == null) {
            System.err.println("Could not retrieve movie list");
        } else {
            for (Iterator it = movies.iterator(); it.hasNext();) {
                Movie movie = (Movie) it.next();
                System.out.println("Title: " + movie.getTitle());
            }
        }
    }
}

이제 Activator 가 재미있어 보이기 시작합니다. 처음에 start 메소드에서 MovieLister 가 사용할 ServiceTracker 개체를 생성합니다. 그리고는 ServiceTracker 를 “엽니다”. 이건 MovieFinder 서비스의 Instance를 레지스트리에서 추적하는걸 시작하라는 것이죠. 그리고는 MovieLister 인터페이스 이름으로 서비스 레지스트리에 MovieListerImpl 개체를 생성하고 등록합니다. 마지막으로, 우리가 번들을 시작했을때 뭔가 재미있는것이 보일수 있도록, MovieLister 를 이용하여 간단한 검색을 실행하고 결과를 출력합니다.

이제 이 번들을 만들고 설치해야 합니다. 자세한 설명은 하지 않도록 하겠습니다. 이전 회를 참고하면 충분히 하실수 있을겁니다. Manifest 파일을 만들고, Bundle-Activatorosgitut.movies.impl.MovieListerActivator 를 지정해야 하는걸 기억해 두세요. 또한 Import-Package 에는 우리가 다른 번들에서 임포팅하는 3개의 패키지 ( org.osgi.framework , org.osgi.util.tracker 그리고 osgitut.movies ) 를 적어주어야 합니다.

MovieLister.jar 를 Equinox 런타임안에 설치했다면, 시작할 수 있습니다. 지난번에 만든 BasicMovieFinder 번들이 동작하고 있는지에 따라 다음 2개의 메시지중 하나를 볼수 있습니다. 만약 동작중이 아니라면,

osgi> start 2
Could not retrieve movie list

아직 동작중이라면

osgi> start 2
Title: Spirited Away

각 번들을 중지시키고 시작시켜보면, 두개의 메시지를 원하는 대로 보실수 있습니다. 이것이 이번 연재의 거의 다입니다만, 제가 서비스가 사용 불가능할때(not available) 할수 있는 일중에 기다리는 방법이 있다고 한거 기억하시나요 ? 우리가 가지고 있는 코드만 있으면 이건 간단합니다. MovieListerImpl 의 16번째 라인을 getService() 메소드 대신 ServiceTrackerwaitForService(5000)으로 변경하시고, InterruptedException 에 대한 try/catch 블록을 추가하세요.

이것은 listByDirector() 메소드가 5000 밀리세컨드동안 MovieFinder 서비스가 나타날때까지 기다리도록 할것입니다. 만약 MovieFinder 서비스가 그 시간내에 설치된다면 (물론 이미 있을때에도) 우린 바로 서비스를 가져와서 사용이 가능할 것입니다.

일반적인 경우에 저는 이런식으로 중지하고 있는 쓰레드를 사용하라고 권고하지만, 이 경우엔 listByDirecor() 메소드가 프레임워크 쓰레드로 부터 호출되는 Bundle activator 의 start 메소드 에서 호출이 되었기 때문에 위험할수 있습니다. 번들이 활성화 될때 여러 일들이 일어나야할 필요가 있기때문에 Activator 들은 빨리 리턴해야 합니다. 최악의 경우에는 우리가 다른것에 의해 이미 lock 되었을지도 모르는 프레임워크 소유개체의 synchronized 블록에 들어갔으므로 deadlock 이 발생할 수도 있습니다. 기본 가이드라인은, 프레임워크에 의해 호출되는 모든코드 또는 번들의 activator 에 있는 start 메소드에서는 시간이 오래 걸리는 작업이나 블록킹 오퍼레이션을 하지 말라는 것입니다.

다음 회에선 의존개체가 없을 경우의 신비한 3번째 옵션 “Don’t exist in the first place” 에 대해 알아보겠습니다. 기대해 주세요!

OSGi 시작하기 5 – 서비스 사용하기 : [번역] Consuming a Service”에 대한 24개의 생각

  1. 오류문의

    osgi> start 29
    org.osgi.framework.BundleException: The bundle could not be resolved. Reason: mi
    ssing imported package osgitut.movies_[1.0.0,2.0.0)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:296)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:266)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:232)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:145)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:294)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:279)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:237)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:208)
    at java.lang.Thread.run(Thread.java:534)

    위와같이 오류가 났습니다. 어찌해야 할까요 ㅠㅠ 후,,,하루종일 해도 챕터 5번을 성공시키지 못하고 있는 저입니다!

    응답
    1. 구루

      현재 프레임워크에 osgitut.movies 번들이 설치되어 있나요 ? 한번 ss 치셔서 해당 번들이 있는지 확인해주세요.

      응답
  2. 오류문의

    참고로 MovieLister.mf 파일 내용은 아래와 같습니다!

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: Movie Lister
    Bundle-SymbolicName: MovieLister
    Bundle-Version: 1.0.0
    Bundle-Activator: osgitut.movies.impl.MovieListerActivator
    Import-Package: org.osgi.framework, org.osgi.util.tracker, osgitut.movies;version=”[1.0.0,2.0.0)”

    응답
  3. 오류문의

    아참 이런질문 바보같을수도 있는데 번들 언인스톨하고 꺼도 나중에 다시 새로운 번들 설치할때는 왜 자꾸 번들 번호가 늘어날까요?? 설치했다 지우면 그 아이디도 지워져야 하는거 아닌가요? 번들 아이디가 무한정 늘어날까봐 겁이나네요. 어떤식으로 해야 번들 번호를 초기화 시킬수 있는지….그리고 번들번호를 썼다가 그번들 지우면 번들 번호도 지워지게 할수 있는지 궁금합니다

    응답
    1. 구루

      프레임워크가 각 번들을 식별할수 있는 unique id 이기 때문에 해당번들에 고정이 되어버립니다.
      Long 값이라 왠만큼 사용하셔서는 문제 안될겁니다. 🙂

      응답
  4. 오류문의

    jar 파일 전부 설치 해보고도 해보고 안해보고도 해봤습니다. 목록은

    equinox.jar
    MoviesInterface.jar
    BasicMovieFinder.jar
    MovieLister.jar (이건 챕터5장에서 만들어서 설치하고 실행 함)

    왜 start가 안먹힐지? 컴파일이나 jar 파일 만드는데 문제가 있었나요?아래처럼 컴파일하고 jar파일 만든후에 실행했어요

    javac -classpath equinox.jar;MoviesInterface.jar osgitut/movies/impl/*.java osgitut/movies/*.java
    jar -cfm MovieLister.jar MovieLister.mf osgitut/movies/impl/*.class osgitut/movies/*.class

    응답
  5. 오류문의

    위와같은 에러와 더불어 간혹 이런식의 에러나 나기도 합니다!

    osgi> ss

    Framework is launched.

    id State Bundle
    0 ACTIVE system.bundle_3.1.0
    40 ACTIVE BasicMovieFinder_1.0.0
    41 RESOLVED MoviesInterface_1.0.0
    42 RESOLVED MovieLister_1.0.0

    osgi> start 42
    org.osgi.framework.BundleException: The activator osgitut.movies.impl.MovieListe
    rActivator for bundle MovieLister is invalid
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:151)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:965)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:321)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:266)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:232)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:145)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:294)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:279)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:237)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:208)
    at java.lang.Thread.run(Thread.java:534)
    Caused by: java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:1618)
    at java.lang.Class.getConstructor0(Class.java:1930)
    at java.lang.Class.newInstance0(Class.java:278)
    at java.lang.Class.newInstance(Class.java:261)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:146)
    … 14 more
    Nested Exception:
    java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:1618)
    at java.lang.Class.getConstructor0(Class.java:1930)
    at java.lang.Class.newInstance0(Class.java:278)
    at java.lang.Class.newInstance(Class.java:261)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:146)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:965)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:321)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:266)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:232)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:145)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:294)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:279)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:237)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:208)
    at java.lang.Thread.run(Thread.java:534)
    Nested Exception:
    java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:1618)
    at java.lang.Class.getConstructor0(Class.java:1930)
    at java.lang.Class.newInstance0(Class.java:278)
    at java.lang.Class.newInstance(Class.java:261)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:146)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:965)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:321)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:266)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:232)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:145)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:294)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:279)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:237)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:208)
    at java.lang.Thread.run(Thread.java:534)

    응답
    1. 구루

      보통 activator 오류는 MANIFEST.MF 가 잘못되어서(맨뒤에 빈줄이 없거나..) Activator 를 못찾는 오류입니다. 저 위에 인터페이스를 못찾는 에러는 osgi 커맨드 창에서 bundle 41 (위에 SS 결과를 따른다고 하면) 이라고 쳐서 MoviesInterface 번들이 정말 인터페이스를 export 하고 있는지 확인 해보시기 바랍니다.

      응답
  6. 오류문의

    osgi> ss

    Framework is launched.

    id State Bundle
    0 ACTIVE system.bundle_3.1.0
    48 RESOLVED MovieLister_1.0.0
    49 ACTIVE MoviesInterface_1.0.0

    osgi> bundle 49
    file:MoviesInterface.jar [49]
    Id=49, Status=ACTIVE Data Root=C:JavaExosgiEXconfigurationorg.eclipse
    .osgiundles49data No registered services.
    No services in use.
    Exported packages
    osgitut.movies; specification-version=”1.0.0″[exported]
    No imported packages
    No fragment bundles
    Named class space
    MoviesInterface; bundle-version=”1.0.0″[provided]
    No required bundles

    이와같은 식으로 확인이 됬습니다,,export는 된듯한데 머가 문제일까요? 첫번째 쓴 오류 구문이 궁금하네요,

    응답
    1. 구루

      흠.. 정확히 어떤 문제인지 모르겠네요. 한번 실행폴더 아래의 configuration 폴더를 지우거나 딴데로 옮긴후에 깨끗한 프레임워크 상태에서 시도해보시겠습니까 ? 같은 번들을 추가/삭제 및 업데이트를 여러번 하다보면 가끔 그런일이 있기도 했는데, 그것때문인지는 잘 모르겠군요.. 휴.. 어렵습니다 ^^;

      응답
  7. org.osgi.framework.BundleException: The activator osgitut.movies.impl.MovieListe
    rActivator for bundle MovieLister is invalid
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:141)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:970)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:346)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:260)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:252)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:260)
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:150)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:300)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:285)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:221)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:136)
    … 13 more
    Nested Exception:
    java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:136)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:970)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:346)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:260)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:252)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:260)
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:150)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:300)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:285)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:221)
    at java.lang.Thread.run(Unknown Source)
    Nested Exception:
    java.lang.NoClassDefFoundError: osgitut/movies/MovieLister
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadBundleAct
    ivator(AbstractBundle.java:136)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(Bund
    leContextImpl.java:970)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:346)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:260)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:252)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:260)
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:150)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:300)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(Fra
    meworkConsole.java:285)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:221)
    at java.lang.Thread.run(Unknown Source)

    이건 무슨에러인가요…ㅠㅠ 5번 따라하는데 리스너를 인스톨시키고 실행을 해도 위같은결과가 안나옵니다..
    리스너를 start하면 위같은에러가나오고요..ㅠㅠ

    응답
    1. 구루

      Activator 에러는 MANIFEST.MF 가 잘못된 경우가 대부분입니다. MANIFEST.MF 마지막에 빈줄이 있는지 확인 부탁드립니다.

      응답
  8. javac 컴파일 명령어랑 jar 만드는 명령어 좀 적어주실수있나요..??ㅠㅠ
    mf파일은 제대로 되어있는거같은데..

    명령어좀 적어주세요..ㅠㅠ

    응답
    1. 구루

      > javac -classpath equinox.jar HelloActivator.java

      > jar -cfm HelloWorld.jar HelloWorld.mf HelloActivator.class

      명령은 1번 강좌에 있듯이 위와 같습니다.

      응답
  9. 이승철

    아마도 MovieLister를 MovieInterface에 넣고 컴파일 한 것이 반영이 안되서 그런 듯 싶습니다.

    응답
  10. 없다캐라

    MovieLister 를 MoviesInterface 번들 프로젝트에서 작성하니깐 되네요. ㅡㅡ; 위의 java.lang.NoClassDefFoundError: osgitut/movies/MovieLister 처럼 MovieLister 클래스를 못찾는 것이 import 해서 MoviesInterface 의 패키지를 참조할 수 있는데 MovieLister를 MovieLister 번들 프로젝트에서 작성하니깐 참조할 수 있는 것이 2군데가 되어서 그런가 봅니다. 이것땜시 반나절 삽질 했더니만 머리 아프네요.

    응답
  11. solemaker

    최근에 http://www.ksug.org를 통해서 이 블로그를 알게되었습니다.
    저도 위와 똑같은 문제로 고민하다, “없다캐라”님과 같은 방법으로 해결하였지만, 글원본의 댓글#15에서 더 많은 정보를 얻을 수 있었습니다.
    (제가 적은 내용보다 직접 방문하셔서 확인하시면 좋을 것 같습니다.^^)
    일단,정리하면 OSGi R4규격 중 “섹션3.8.4 Overall Search Order”
    때문에 발생하는 문제입니다.
    MovieLister번들의 MovieListerActivator가 MovieLister.mf의 Import-Package를 osgitut.movies를 정의하고 있어,
    MovieLister번들 내부의 MovieLister를 검색하지 않기 때문에 발생하는 문제입니다.
    이 문제를 해결하기 위해서는 참조하지 못하는 osgitut.movies.MovieLister를 MoviesInteface번들에 포함시켜, 위의 문제를 해결해야 합니다. 그렇다고 package가 동일하다고 무조건 한 번들에 합쳐야 하는 것은 아닙니다. (위 내용도 글원본 포스팅중에 일부가 있으니 참조하세요.)
    from 늦깍이, solemaker

    응답
  12. 머리가아프네요

    흠… 사실 잘 이해가 안되는 것들 투성입니다;;
    1. 소스 코드 작성
    osgitut.movies.Movie.java
    osgitut.movies.MovieFinder.java
    osgitut.movies.MovieLister.java
    2. 코드 컴파일
    javac osgitut\movies\*.java
    3. Jar 파일 생성
    jar cfm MoviesInterface.jar MoviesInterface.mf osgitut\movies\*.class
    4. 코드 작성
    osgitut.movies.impl.MovieListerActivator.java
    osgitut.movies.impl.MovieListerImpl.java
    5. 코드 컴파일
    javac -classpath equinox.jar;MoviesInterface.jar osgitut\movies\impl\*.java
    *Note 메시지 발생
    : Note: osgitut\movies\impl\MovieListerImpl.java uses unchecked or unsafe operations.
    Note: Recompile with -Xint:unchecked for details.
    하지만 class 파일들은 생성됨.
    6. Jar 파일 생성
    jar cfm MovieListerActivator.jar MovieListerActivator.mf osgitut\movies\*.class
    7. Bundle Install
    osgi> install MoviesInterface.jar
    osgi> install MovieListerActivator.jar
    osgi> ss
    id state bundle
    12 Installed MoviesInterface_1.0.0
    13 Installed MovieListerActivator
    osgi> update 12
    osgi> refresh 12
    8. 실행
    osgi> start 13
    org.osgi.framework.BundleException: The bundle “MovieListerActivator_1.0.0 [13]” could not be resolved. Reason: Missing Constraint: Import-Package: osgitut.movies; version=”0.0.0″
    org.osgi.framework.BundleException: The bundle “MovieListerActivator_1.0.0 [13]”
    could not be resolved. Reason: Missing Constraint: Import-Package: osgitut.movi
    es; version=”0.0.0″
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverEr
    ror(AbstractBundle.java:1317)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolution
    FailureException(AbstractBundle.java:1301)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:319)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:284)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:276)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:252)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:155)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:156)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(
    FrameworkConsole.java:141)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:105)
    at java.lang.Thread.run(Unknown Source)
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 INSTALLED BasicMovieFinder_1.0.0
    12 RESOLVED MoviesInterface_1.0.0
    13 INSTALLED MovieListerActivator_1.0.0
    osgi> update 13
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 INSTALLED BasicMovieFinder_1.0.0
    12 RESOLVED MoviesInterface_1.0.0
    13 INSTALLED MovieListerActivator_1.0.0
    osgi> refresh 13
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 INSTALLED BasicMovieFinder_1.0.0
    12 RESOLVED MoviesInterface_1.0.0
    13 INSTALLED MovieListerActivator_1.0.0
    osgi> start 13
    org.osgi.framework.BundleException: The bundle “MovieListerActivator_1.0.0 [13]”
    could not be resolved. Reason: Missing Constraint: Import-Package: osgitut.movi
    es; version=”0.0.0″
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverEr
    ror(AbstractBundle.java:1317)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolution
    FailureException(AbstractBundle.java:1301)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:319)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:284)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:276)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:252)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:155)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:156)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(
    FrameworkConsole.java:141)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:105)
    at java.lang.Thread.run(Unknown Source)
    제가 수행했던 과정들을 적어보았습니다.
    왜 안되는지 모르겠네요…
    어렵습니다 OSGI…
    개념들도 잘 머리에 안 와닿네요;;

    응답
  13. 머리가아프네요

    뒷부분이 잘못 복사됐네요.. 다시 작성합니다..
    osgi> install file:MoviesInterface.jar
    Bundle id is 14
    osgi> install file:MovieListerActivator.jar
    Bundle id is 15
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 INSTALLED BasicMovieFinder_1.0.0
    14 INSTALLED MoviesInterface_1.0.0
    15 INSTALLED MovieListerActivator_1.0.0
    osgi> update 14
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 INSTALLED BasicMovieFinder_1.0.0
    14 INSTALLED MoviesInterface_1.0.0
    15 INSTALLED MovieListerActivator_1.0.0
    osgi> refresh 14
    osgi> ss
    Framework is launched.
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.6.2.R36x_v20110210
    5 ACTIVE BasicMovieFinder_1.0.0
    14 RESOLVED MoviesInterface_1.0.0
    15 INSTALLED MovieListerActivator_1.0.0
    osgi> start 15
    org.osgi.framework.BundleException: The bundle “MovieListerActivator_1.0.0 [15]”
    could not be resolved. Reason: Missing Constraint: Import-Package: osgitut.movi
    es.impl; version=”[1.0.0,2.0.0)”
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverEr
    ror(AbstractBundle.java:1317)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolution
    FailureException(AbstractBundle.java:1301)
    at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(Bundl
    eHost.java:319)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:284)
    at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(Abstrac
    tBundle.java:276)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._st
    art(FrameworkCommandProvider.java:252)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.
    execute(FrameworkCommandInterpreter.java:155)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(F
    rameworkConsole.java:156)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(
    FrameworkConsole.java:141)
    at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(Framewo
    rkConsole.java:105)
    at java.lang.Thread.run(Unknown Source)
    osgi>
    —————————————–
    고수님들께서 좀 보고 뭐가 잘못된 것인지 봐주셨으면 합니다. 부탁드립니다.

    응답
  14. dave

    MovieLister를 MovieInterface에 포함시키라는 말이 이해 안되시는 분은,

    [OSGi 시작하기 3]
    > javac osgitut/movies/Movie.java osgitut/movies/MovieFinder.java
    > jar -cfm MoviesInterface.jar MoviesInterface.mf osgitut/movies/*.class

    이 부분을,
    > javac osgitut/movies/Movie.java osgitut/movies/MovieFinder.java osgitut/movies/MovieLister.java
    > jar -cfm MoviesInterface.jar MoviesInterface.mf osgitut/movies/*.class

    이렇게 재실행하시고,

    osgi> ss

    Framework is launched.

    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
    1 RESOLVED HelloWorld_1.0.0
    2 ACTIVE BasicMovieFinder_1.0.0
    4 ACTIVE MoviesInterface_1.0.0
    6 INSTALLED MovieLister_1.0.0

    update와 refresh를 해 보시면, 될 겁니다.

    osgi> diag 6
    file:MovieLister.jar [6]
    No unresolved constraints.

    osgi> refresh 6

    osgi> Title: Spirited Away

    osgi> ss

    Framework is launched.

    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.4.0.v20080605-1900
    1 RESOLVED HelloWorld_1.0.0
    2 ACTIVE BasicMovieFinder_1.0.0
    4 ACTIVE MoviesInterface_1.0.0
    6 ACTIVE MovieLister_1.0.0

    osgi>

    응답

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다