2013-09-25 3 views
0

가능한 한 많은 모듈성을 가진 OSGi 환경 (Karaf running Felix)에서 지속성을 유지하려고합니다. JPA 대신 추가 기능 (주로 그룹 가져 오기)을 위해 JDO를 선택했습니다. 구현은 Datanucleus입니다. Maven을 사용하여 전체 프로젝트를 빌드합니다.Datanucleus JDO와 청사진을 사용하는 OSGi 환경에서의 지속성

이전에 JDO 또는 OSGi에 대한 경험이 없었기 때문에 두 가지 중 하나를 작동 시키려면 상당한 어려움이있었습니다. 나는 현재 Java SE 환경에서 JDO 지속성을 수행 할 수 있으며 (유닛 테스트는 문제없이 작동 함) 청사진 컨테이너를 사용하여 OSGi 환경에서 서비스를 제공하는 방법을 알고 있습니다. 그러나 나는이 두 가지가 함께 작동하도록 할 수는 없다. 클래스 로딩 문제가 있습니다.

Karaf에서 JDO 지속성을 수행 할 수있는 간단한 애플리케이션조차 만들 수 없었습니다. (나는 this tutorial을 시도했지만 스프링 DM을 사용하고 대신 OSGi 청사진을 사용하기 위해 다시 작성할 수 없었습니다).

내가 대해 가장 혼란 스러워요 것은 :

  • 어떤 가치 나는 datanucleus.primaryClassLoader 속성을 설정해야합니다에?
  • JDOHelper.getPersistenceManagerFactory 메소드에 전달할 클래스 로더는 무엇입니까?
  • maven-bundle-plugin을 사용하여 명시 적으로 가져올 패키지는 무엇입니까?
  • 다른 번들 된 PersistenceManagerFactory에 대한 참조 외에 무엇이 필요합니까 (javax.jdo, org.datanucleus.api.jdoorg.osgi.framework 자 적어도 처럼해야 할 수도 있습니다 보이는)?

또한 :

  • 는 값 클래스에서 지속성 정보를 분리 할 수 ​​있습니까? 만약 내가 올바르게 이해한다면, 그것은 실행 가능하다면 매우 복잡 할 수있는 런타임 향상을 사용하는 경우에만 가능할 것입니다.
  • 여러 번들에서 상호 의존성 지속 가능 클래스를 정의 할 수 있습니까? 하나의 묶음에 정의 된 사용자와 다른 묶음에있는 주소를 갖는 것과 같이?

Datanucleus, JDO API 및 OSGi 청사진을 사용하여 지속성을 관리하는 간단한 다중 번들 프로젝트의 예제에 대해 매우 감사하게 생각합니다.

답변

0

난 단지 Karaf 위에 작동하는 JDO/datanucleus을 얻기에 관하여 몇 가지 기본적인 힌트를 제공 할 수 있습니다 감사합니다.

자습서에서 지적한대로 LocalPersistenceManagerFactoryBean을 확장하고 BundleContextAware 인터페이스도 구현해야합니다.

여기서 핵심 포인트는 클래스 로딩입니다. LocalPersistenceManagerFactoryBean은 모든 클래스가 하나의 단일 클래스 로더에 의해로드 될 것으로 예상합니다. 이는 OSGi 런타임에는 해당되지 않습니다.

  1. 가 명시 적으로 매니페스트 파일에 org.datanucleus.api.jdo을 가져옵니다에 당신이 필요합니다 작업을 얻기 위하여

    .

  2. datanucleus.primaryClassLoader 속성은 JDOHelper.getPersistenceManagerFactory 메서드에 전달할 동일한 클래스 로더로 설정할 수 있습니다. 클래스 로더는 org.datanucleus.api.jdo 번들에서 사용하는 클래스 로더입니다 (아래 예제 참조)
  3. datanucleus.plugin.pluginRegistryClassName 속성을 org.datanucleus.plugin.OSGiPluginRegistry으로 설정해야합니다. 정지 할 때
  4. 은/번들을 제거, 당신은 지속성 관리자 공장 (주제에 this question 확인)

샘플 사용자 정의 LocalPersistenceManagerFactoryBean를 다시 만드는 오류를 방지하기위한 javax.jdo 번들을 갱신해야합니다 :

public class OSGiLocalPersistenceManagerFactoryBean 
    extends LocalPersistenceManagerFactoryBean implements BundleContextAware { 

    public static final String JDO_BUNDLE_NAME = "org.datanucleus.api.jdo"; 
    public static final String JDO_PMF_CLASS_NAME = "org.datanucleus.api.jdo.JDOPersistenceManagerFactory"; 

    private BundleContext bundleContext; 

    @Override 
    protected PersistenceManagerFactory newPersistenceManagerFactory(String name) { 
     return JDOHelper.getPersistenceManagerFactory(name, getClassLoader()); 
    } 

    @Override 
    protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) { 
     ClassLoader classLoader = getClassLoader(); 

     props.put("datanucleus.primaryClassLoader", classLoader); 

     if (FrameworkUtil.getBundle(this.getClass()) != null) { // running in OSGi 
      props.put("datanucleus.plugin.pluginRegistryClassName", "org.datanucleus.plugin.OSGiPluginRegistry"); 
     } 

     PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props, classLoader); 

     return pmf; 
    } 

    private ClassLoader getClassLoader() { 
     ClassLoader classLoader = null; 
     Bundle thisBundle = FrameworkUtil.getBundle(this.getClass()); 

     if (thisBundle != null) { // on OSGi runtime 
      Bundle[] bundles = bundleContext.getBundles(); 

      for (Bundle bundle : bundles) { 
       if (JDO_BUNDLE_NAME.equals(bundle.getSymbolicName())) { 
        try { 
         classLoader = bundle.loadClass(JDO_PMF_CLASS_NAME).getClassLoader(); 
        } catch (ClassNotFoundException e) { 
         // do something fancy here ... 
        } 
        break; 
       } 
      } 
     } else { // on Java runtime 
      classLoader = this.getClass().getClassLoader(); 
     } 
     return classLoader; 
    } 

    @Override 
    public void setBundleContext(BundleContext bundleContext) { 
     this.bundleContext = bundleContext; 
    } 
} 
+0

감사합니다. 제가 확인하겠습니다. – binarek

+0

번들을 시작할 때 모든 데이터 핵 번들을 시작해야합니다. 그렇지 않으면 OSGIPluginRegistry에서 오류 (NullPointerException)가 발생합니다. –

관련 문제