2012-12-03 2 views
3

퓨즈 ESB (Apache ServiceMix 및 Karaf)에서 OSGI 서비스로 공개하려는 인터페이스가있는 코어 라이브러리가 있습니다. 목표는 다른 번들이이를 사용할 수있게하는 것입니다. 이 서비스는 JPA (OpenJPA)와 Spring을 사용합니다.OSGI 서비스 JPA PersistenceContext가 삽입되지 않았습니다.

public interface PatientService { 
    public Patient find(Integer id); 
} 

및 클래스 : 다음은 인터페이스

@Repository 
public class PatientServiceJpaImpl implements PatientService { 
    @PersistenceContext(unitName="psu") 
    private EntityManager entityManager; 

    @Override 
    public Patient find(Integer id) { 
     return entityManager.find(Patient.class, id); 
    } 
} 

다음은 인 META-INF/spring/beans.xml 생략 :

<beans xmlns="http://www.springframework.org/schema/beans" ...> 
    <context:annotation-config /> 
    <context:component-scan base-package="..." /> 

    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="emf" /> 
    </bean> 

    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="psu" /> 
     <property name="jpaVendorAdapter" ref="jpaAdapter" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter" /> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
     <property name="driverClassName" value="${database.driver}" /> 
     <property name="url" value="${database.url}" /> 
     <property name="username" value="${database.username}" /> 
     <property name="password" value="${database.password}" /> 
    </bean> 

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/> 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 
</beans> 

그리고 META-INF/persistence.xml (약어 사용) :

<persistence xmlns="http://java.sun.com/xml/ns/persistence" ...> 
    <persistence-unit name="psu" transaction-type="RESOURCE_LOCAL"> 
     <class>...</class> 
</persistence> 

비 OSGi 환경에서는 모든 것이 훌륭하게 작동합니다. 그것은 그래서 OSGi 서비스를 생성, 펠릭스 받는다는 - 번들 - 플러그인을 사용하여, 나는 다음과 같은 OSGI-INF/blueprint/osgi-context.xml 추가 :

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 
    http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> 

    <bean id="patientService" class="com.test.service.PatientServiceJpaImpl" /> 
    <service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" /> 

</blueprint> 

를 번들이 성공적으로 배포되고 서비스가 등록되어 있습니다. 문제는 PatientService이 다른 번들에서 참조 될 때 엔티티 관리자가 삽입되지 않아서 find(Integer id) 메소드에서 NullPointerException을 던지는 것입니다. 다음은 소비자의 META-INF/spring/consumer-context.xml의 조각입니다 :

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:jaxws="http://cxf.apache.org/jaxws" 
xmlns:osgi="http://www.springframework.org/schema/osgi" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd 
    http://cxf.apache.org/jaxws 
    http://cxf.apache.org/schemas/jaxws.xsd 
    http://www.springframework.org/schema/osgi 
    http://www.springframework.org/schema/osgi/spring-osgi.xsd"> 

    <bean id="patientServiceImpl" class="com.test.ws.PatientWebServiceImpl" > 
     <property name="patientService"> 
      <osgi:reference interface="com.test.service.PatientService"/> 
     </property> 
    </bean> 

    ... 

</beans> 

그냥 명확하게하기 위해이의 PatientService 소비자 번들에 주입하지만, 엔티티 관리자가 제공 번들에 주입되지 않습니다. 원래 서비스를 시작할 때 또한,이 이유는 다음과 로그 출력에 퍼시스턴스 유닛의 문제로 나타나지 않습니다

125 psu TRACE [SpringOsgiExtenderThread-14] openjpa.Runtime - [email protected] creating container [email protected] for PU psu. 

는 무슨 일이 일어나고 있는지 아이디어를 얻을하기를, 나는 개체 메모리 참조를 기록하고 스택 추적은 PatientServiceJpaImpl 클래스의 생성자에 있습니다. 생성자 회 (두 개의 다른 물체를 만드는)라고 하였다

  1. 제 1 출력은 org.apache.felix 다소간 org.apache.aries.blueprint 끝나는에서 시작 OSGi 컨테이너에서 발생하는 것으로 보인다.

  2. 두 번째 결과는 org.springframework.osgi부터 시작하여 org.springframework.beans.BeanUtils으로 끝나는 스프링 프레임 워크에서 비롯된 것 같습니다.

소비자 서비스가 호출되면 참조가 삽입 된 엔티티 관리자가없는 청사진 인스턴스 개체입니다. 또한 로그에서 지속성 단위는 PatientServiceJpaImpl 개체의 청사진 인스턴스 생성 후에 인스턴스화됩니다.

나는이 문제를 꽤 오랫동안 수색 해 봤지만 아이디어가 부족합니다. 아이러니 한 점은 실제로 한 지점에서 효과가 있었다는 것입니다. 그러나 나는 그것이 성공적으로 벗어날 수없는 쥐 둥지 였기 때문에 작동하도록 많은 변화를 만들었습니다.

청사진 관리 객체에 지속성 컨텍스트가 삽입되지 않는 이유는 무엇입니까? 어떤 아이디어라도 감사 할 것입니다. 감사.

답변

2

이것이 제대로 작동하는지 확신 할 수 없으므로 스프링을 청사진과 함께 사용하게됩니다. 청사진을 기반으로하는 업무용 응용 프로그램을 가지고 있으며 매우 만족합니다. 귀하의 유스 케이스에 대해서는 적어도 JPA 부분에 대한 청사진을 사용하는 것이 좋습니다. jpa 클래스를 서비스로 사용하려면 여전히 spring-dm을 사용할 수 있습니다.

<blueprint default-activation="eager" 
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0"> 

<bean id="patientService" class="com.test.service.PatientServiceJpaImpl" > 
    <jpa:context property="em" unitname="dn1" /> 
<tx:transaction method="*" value="Required" /> 
</bean> 
<service id="osgiPatientService" ref="patientService" interface="com.test.service.PatientService" /> 
</blueprint> 

PatientServiceJPAImpl 특수 효과를 포함하지 않기로 변경했습니다.

public class PatientServiceJpaImpl implements PatientService { 
    protected EntityManager em; 

    @Override 
    public Patient find(Integer id) { 
     return em.find(Patient.class, id); 
    } 
} 
+0

응답 해 주셔서 감사합니다. 이 라이브러리는 비 OSGI 환경에서 다른 개발자가 사용합니다. 두 가지 솔루션을 모두 유지할 수있는 방법이 있습니까? 즉, 청사진 환경에서 'PatientServiceJpaImpl'주석을 유지하면 어떤 영향을 미칩니 까? –

+0

그런 경우 청사진을 통해 서비스를 내보내지는 않지만 spring-dm을 사용하여 서비스를 내보내고 있는지 확인하십시오. spring-dm에 스프링 스틱을 사용해야하고 청사진을 통해 서비스를 참조해야하는 경우 둘 모두의 혼합이 작동하지 않습니다. –

+0

원래 스프링 컨텍스트 xml 파일에서 osgi 서비스를 정의하여이를 시도했습니다. 그러나 felix maven-bundle-plugin을 사용하여 번들을 빌드 한 후에 MANIFEST-MF에서 Export-Service 선언을 보지 못했으며 번들을 배포해도 서비스가 등록되지 않았습니다. 나는 봄 DM이 중단 된 것처럼 보이기 때문에 후속 조치를하지 않기로 결정했다. karaf에서 spring-dm을 사용할 수 있습니까? (Fuse ESB 배포판을 사용하고 있습니까?) 그렇다면 길 아래로하는 것이 합리적입니까? 감사. –

0

이 문제를 해결하는 좋은 방법은 Gemini JPA입니다. Gemini JPA를 사용하면 JPA 번들이 persistence.xml의 구성을 기반으로 EntityManagerFactory OSGi 서비스를 자동으로 노출합니다. 따라서 JPA 클라이언트 번들에서 청사진은 지속성 단위 이름을 지정하는 필터 조건으로이 서비스를 가져와야합니다.

여기에 그 라인에 작은 구현의 : mvc-osgi

기전력 서비스가 당신을 위해 작동하지 않는 경우, 수동으로 EMF를 만들 번들 쌍둥이 자리 JPA에 의해 노출 된 EntityManagerFactoryBuilder 서비스를 사용할 수 있습니다. 이렇게하려면 "createEntityManagerFactory"를 호출해야합니다.

관련 문제