이 글은 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 >
마지막 글에서 우린 어떻게 서비스를 등록하는지에 대해 알아봤습니다. 이제 그 서비스를 찾고 다른 번들에서 그 서비스를 이용하도록 작업해 봅시다.
Martin Folwer의 Dependency Injection에 대한 글에서 영감을 얻었던 지난번처럼, 우린 문제를 우리 요구사항에 포함할 것입니니다. 우린 MovieFinder
를 서비스로 만들어서 서비스 레지스트리에 등록했습니다. 이젠 특정 감독에 의해 제작된 영화를 찾기위해 MovieFinder
를 사용하는 MovieLister
를 만들어볼 것입니다. 그리고 이 MovieLister
자체도 GUI Application 같은 다른 특정번들에 사용되는 서비스가 될것이라고 가정합니다. 여기서 문제점은, OSGi 서비스는 동적이라 등록되고 사라지고 한다는것입니다. 즉, 우리가 MovieFinder
서비스를 호출하고자 할때, 서비스가 불가능할수도 있습니다.
그러면, 만약 MovieFinder
서비스가 존재하지 않는다면 MovieLister
는 무엇을 해야할까요 ? MovieLister
가 하는 일중에 MovieFinder
에 대한 호출이 매우 중요한 것이라는것은 확실하므로, 우리가 선택할수 있는 옵션은 몇가지 밖에 없습니다.
- 에러를 낸다. (Null 을 리턴하거나 Exception 을 내거나)
- 기다린다.
- 처음부터 아예 설치가 안되도록 한다. ( 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
를 사용하지 않고 레지스트리에서 서비스를 가져오는 코드를 보셨을수도 있습니다. 예를 들어 BundleContext
에 getServiceReferece
와 getService
를 호출하는것이 가능합니다. 하지만 이런 코드는 꽤 복잡하고 사용후 잘 지우도록 조심해야 합니다. 제 의견으론, 로우레벨 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-Activator
에 osgitut.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()
메소드 대신 ServiceTracker
의 waitForService(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> 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번을 성공시키지 못하고 있는 저입니다!
현재 프레임워크에 osgitut.movies 번들이 설치되어 있나요 ? 한번 ss 치셔서 해당 번들이 있는지 확인해주세요.
참고로 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)”
아참 이런질문 바보같을수도 있는데 번들 언인스톨하고 꺼도 나중에 다시 새로운 번들 설치할때는 왜 자꾸 번들 번호가 늘어날까요?? 설치했다 지우면 그 아이디도 지워져야 하는거 아닌가요? 번들 아이디가 무한정 늘어날까봐 겁이나네요. 어떤식으로 해야 번들 번호를 초기화 시킬수 있는지….그리고 번들번호를 썼다가 그번들 지우면 번들 번호도 지워지게 할수 있는지 궁금합니다
프레임워크가 각 번들을 식별할수 있는 unique id 이기 때문에 해당번들에 고정이 되어버립니다.
Long 값이라 왠만큼 사용하셔서는 문제 안될겁니다. 🙂
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
위와같은 에러와 더불어 간혹 이런식의 에러나 나기도 합니다!
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)
보통 activator 오류는 MANIFEST.MF 가 잘못되어서(맨뒤에 빈줄이 없거나..) Activator 를 못찾는 오류입니다. 저 위에 인터페이스를 못찾는 에러는 osgi 커맨드 창에서 bundle 41 (위에 SS 결과를 따른다고 하면) 이라고 쳐서 MoviesInterface 번들이 정말 인터페이스를 export 하고 있는지 확인 해보시기 바랍니다.
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는 된듯한데 머가 문제일까요? 첫번째 쓴 오류 구문이 궁금하네요,
흠.. 정확히 어떤 문제인지 모르겠네요. 한번 실행폴더 아래의 configuration 폴더를 지우거나 딴데로 옮긴후에 깨끗한 프레임워크 상태에서 시도해보시겠습니까 ? 같은 번들을 추가/삭제 및 업데이트를 여러번 하다보면 가끔 그런일이 있기도 했는데, 그것때문인지는 잘 모르겠군요.. 휴.. 어렵습니다 ^^;
네 항상 답변 감사드립니다,,깨끗한 프레임워크에서 시도해봐야겠네요^^;
잘 해결되었으면 좋겠네요. 🙂
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하면 위같은에러가나오고요..ㅠㅠ
자세히 보니 위에분과 같은에러군요.. 저도 다 지우고 해봐야하는 문제인가보네요..
Activator 에러는 MANIFEST.MF 가 잘못된 경우가 대부분입니다. MANIFEST.MF 마지막에 빈줄이 있는지 확인 부탁드립니다.
javac 컴파일 명령어랑 jar 만드는 명령어 좀 적어주실수있나요..??ㅠㅠ
mf파일은 제대로 되어있는거같은데..
명령어좀 적어주세요..ㅠㅠ
> javac -classpath equinox.jar HelloActivator.java
> jar -cfm HelloWorld.jar HelloWorld.mf HelloActivator.class
명령은 1번 강좌에 있듯이 위와 같습니다.
저도 같은 에러가 났었는데 MovieInterface를 update하고 refresh를 하니 해결 됐습니다.
아마도 MovieLister를 MovieInterface에 넣고 컴파일 한 것이 반영이 안되서 그런 듯 싶습니다.
MovieLister 를 MoviesInterface 번들 프로젝트에서 작성하니깐 되네요. ㅡㅡ; 위의 java.lang.NoClassDefFoundError: osgitut/movies/MovieLister 처럼 MovieLister 클래스를 못찾는 것이 import 해서 MoviesInterface 의 패키지를 참조할 수 있는데 MovieLister를 MovieLister 번들 프로젝트에서 작성하니깐 참조할 수 있는 것이 2군데가 되어서 그런가 봅니다. 이것땜시 반나절 삽질 했더니만 머리 아프네요.
최근에 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
흠… 사실 잘 이해가 안되는 것들 투성입니다;;
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…
개념들도 잘 머리에 안 와닿네요;;
뒷부분이 잘못 복사됐네요.. 다시 작성합니다..
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>
—————————————–
고수님들께서 좀 보고 뭐가 잘못된 것인지 봐주셨으면 합니다. 부탁드립니다.
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>