OSGI 服务 JPA PersistenceContext 未注入 [英] OSGI service JPA PersistenceContext not injected

查看:33
本文介绍了OSGI 服务 JPA PersistenceContext 未注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个核心库,它有一个接口,我想在 Fuse ESB(Apache ServiceMix 和 Karaf)中将其公开为 OSGI 服务.目标是允许其他包使用它.该服务使用 JPA (OpenJPA) 和 Spring.界面如下:

I have a core library that has an interface that I want to expose as an OSGI service in Fuse ESB (Apache ServiceMix and Karaf). The goal is to allow other bundles to use it. The service uses JPA (OpenJPA) and Spring. The following is the interface:

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 环境中,一切正常.它使用 felix maven-bundle-plugin,因此为了创建 OSGi 服务,我添加了以下 OSGI-INF/blueprint/osgi-context.xml:

In a non-OSGi environment, everything works great. It uses the felix maven-bundle-plugin, so to create the OSGi service, I added the following 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>

bundle 部署成功,服务注册成功.问题是当PatientService被另一个bundle引用时,实体管理器并没有被注入,从而在find(Integer id)<中抛出一个NullPointerException/代码>方法.以下是消费者 META-INF/spring/consumer-context.xml 的片段:

The bundle is deployed successfully and the service is registered. The problem is that when the PatientService is referenced from another bundle, the entity manager has not been injected, thus throwing a NullPointerException in the find(Integer id) method. The following is a snippet of the consumer's 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 被注入到消费者包中,但实体管理器没有被注入到提供者包中.此外,由于启动原始服务时的以下日志输出,它似乎不是持久性单元的问题:

Just to be clear, the PatientService is injected in the consumer bundle, but the entity manager is not injected in the provider bundle. Also, it does not appear to be an issue with the persistence unit due to the following log output when starting the original service:

125  psu  TRACE  [SpringOsgiExtenderThread-14] openjpa.Runtime - org.apache.openjpa.persistence.PersistenceProviderImpl@24a5031d creating container org.apache.openjpa.persistence.EntityManagerFactoryImpl@4d6f77b6 for PU psu.

为了了解发生了什么,我在 PatientServiceJpaImpl 类的构造函数中记录了对象内存引用和堆栈跟踪.构造函数被调用两次(创建两个不同的对象):

To get an idea what is going on, I logged the the object memory reference and stack trace in the constructor of the PatientServiceJpaImpl class. The constructor was called twice (creating two different objects):

  1. 第一个输出似乎源自从 org.apache.felix 开始的 osgi 容器,或多或少以 org.apache.aries.blueprint 结尾.

  1. The first output appears to originate from the osgi container starting from org.apache.felix and more or less ending in org.apache.aries.blueprint.

第二个输出似乎源自 spring 框架,从 org.springframework.osgi 开始,或多或少以 org.springframework.beans.BeanUtils 结尾.

The second output appears to originate from the spring framework starting from org.springframework.osgi and more or less ending in org.springframework.beans.BeanUtils.

当消费者服务被调用时,它所拥有的引用是对蓝图实例化对象的引用,该对象没有注入的实体管理器.同样从日志中,持久性单元在 PatientServiceJpaImpl 对象的蓝图实例化之后实例化.

When the consumer service is called, the reference it has is to the blueprint instantiated object, which does not have an injected entity manager. Also from the logs, the persistence unit is instantiated after the blueprint instantiation of the PatientServiceJpaImpl object.

我已经搜索并修改了这个问题很长一段时间,但我已经没有想法了.具有讽刺意味的是,它实际上曾经有效,但我做了很多改变才能让它工作,以至于我无法成功退出.

I have searched and tinkered with this issue for quite a while and I've run out of ideas. The irony is that it actually worked at one point, but I had made so many changes to get it to work that it was a rats nest that I was not able to back out of successfully.

为什么在蓝图托管对象中没有注入持久化上下文?任何想法将不胜感激.谢谢.

Why is the persistence context not injected in the blueprint managed object? Any ideas will be appreciated. Thanks.

推荐答案

我不确定这是否会奏效,因为您正在将 Spring 与蓝图混合在一起.我有一个仅基于蓝图的工作应用程序,我很高兴.对于您的用例,我建议至少为您的 JPA 部分使用蓝图.您仍然可以使用 spring-dm 将 jpa 类用作服务.

I'm not sure if this is going to work, cause you are mixing spring with blueprint. I have a working application based only on blueprint and I'm quite happy. For your use-case I'd suggest using blueprint at least for your JPA part. You still can use spring-dm for using the jpa classes as services.

<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 我将更改为不包含任何注释.

Your PatientServiceJPAImpl I would change to not contain any annotations.

public class PatientServiceJpaImpl implements PatientService {
    protected EntityManager em;

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

这篇关于OSGI 服务 JPA PersistenceContext 未注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆