2010-04-28 5 views
3

저는 osgi을 처음 접했고 기능적 개념 증명을 함께 얻으려고합니다.felix에서 OSGI 클래스 캐스팅 예외

내 공통 API는 번들 활성기가없는 common-api.jar이라는 이름의 번들로 만들어 지지만 모든 인터페이스를 내 보냅니다. 이 상황에서 주목해야 할 것은 DatabaseService.java이다.

그런 다음 systemx-database-service라는 두 번째 번들이 있습니다. 이는 데이터베이스 서비스 인터페이스를 구현합니다. 이 구현 번들 activator있는 데이터베이스에서 연결 테스트 및 arbitraty 값을 선택합니다. 나는 또한 내가 너무 같은 다른 번들의 사용할 수 원하는 서비스를 등록 :

context.registerService(DatabaseService.class.getName(), new SystemDatabaseServiceImpl(context), new Properties()); 

기본 개념 당신이 SystemDatabaseService 구현을 다시 얻을 것이다 데이터베이스 서비스에 대한 서비스 참조 보면되고.

나는 검사 서비스를 출력 그것은이 작업을 수행 할 때 :

-> inspect s c 69 
System Database Service (69) provides services: 
---------------------------------------------- 
objectClass = za.co.xxx.xxx.common.api.DatabaseService 
service.id = 39 
내가 테스트 번들에서이 작업을 수행하면 믿고 나를 이끌 것

:

context.getService(context.getServiceReference(DatabaseService.class)); 

내가 되돌려 받아야 DatabaseService.class의 인스턴스입니다. 그런 행운은 없습니다. 단순히 서비스를 찾을 수없는 것처럼 보입니다. 여기 나와 함께 스틱을하면 내 이야기가 낯설어진다.

갈 곳이없는 계산하지만까지 나는이 괴물 썼다 :

for (Bundle bundle : bundles) { 
     if (bundle.getSymbolicName().equals("za.co.xxx.xxx.database-service")) { 
      ServiceReference[] registeredServices = bundle.getRegisteredServices(); 
      for (ServiceReference ref : registeredServices) { 
       DatabaseService service = (DatabaseService) context.getService(ref); 
       // use service here. 
       } 
      } 
     } 
    } 

지금 내가 실제로 서비스 참조를 볼 수 있습니다,하지만 난 이후 미친 짓이 오류

java.lang.ClassCastException: za.co.xxx.xxx.database.service.impl.SystemDatabaseServiceImpl cannot be cast to za.co.xxx.xx.common.api.DatabaseService 

를 얻을 구현은 분명히 인터페이스를 구현합니다!

도움을 주시면 감사하겠습니다. 제 생각에 나는 osgi 사고 방식이 매우 새롭기 때문에 여기 내 모든 접근 방식에 결함이있을 수 있습니다.

오. 누군가가 그 매니 페스트를 원한다면 나는 그들을 게시 할 수있다. 그리고 필자는 felix를 빌드하고 실행하기 위해 maven-bnd-plugin을 사용하고있다.

감사

니코

답변

2

테스트 번들이 SystemDatabaseServiceImpl로 DatabaseService 인터페이스의 같은 수입으로 해결해야합니다. 이것이 발생하지 않으면 getServiceReference는 서비스가 발견 되더라도 null을 리턴한다고 문서화합니다. 번들을 수동으로 찾고 서비스와 캐스트를 찾으려고하면 getServiceReference가 이런 식으로 동작하는 이유를 알 수 있습니다. 임의 서비스를 반환하면 Java 캐스트가 실패합니다.

impl bundle과 test bundle 모두 DatabaseService.class.getClassLoader()를 인쇄하여 동일한 번들인지 증명하는 것이 좋습니다. 그렇지 않다면 OSGi MANIFEST.MF 메타 데이터를 조정하여 인터페이스 클래스에 대한 일관된 뷰를 갖도록해야한다.

예를 들어, DatabaseService 인터페이스가 test 번들과 impl 번들 모두에 포함되어 있습니까? 그렇다면 해당 인터페이스를 impl 번들 (및 Export-Package) 또는 세 번째 인터페이스 번들 및 Export-Package로 이동해야합니다.그런 다음 다른 번들을 Import-Package로 조정하십시오.

+1

"클래스 A를 클래스 A로 형변환 할 수 없습니다"라는 것은 여러 클래스 로더가 관련되어 있고 OSGi에 번들마다 클래스 로더가있는 경우의 일반적인 Java 문제입니다. – SteveD

+0

bkail에 얼룩이 있습니다. 클래스 로더에서 sysout을 실행했을 때 [ 69.0 = 대상 서비스 용 클래스 로더 74.0 =이 클래스의 클래스 로더 ]. common-api는 별개의 번들에 있습니다. 이는 구현 및 테스트 번들을 만들기 위해 만든 항아리에서 제외해야 함을 의미합니까? – Nico

+0

감사합니다. 모든 API와 BAM을 제외했습니다. 매력처럼 작동합니다. – Nico

관련 문제