Search code examples
jpaosgiweblogicweblogic12caries

Aries JPA EntityManager services not starting for WebLogic data source


I'm trying to get an OSGi persistence bundle working on WebLogic's built-in Felix framework. As per the WebLogic OSGi documentation, my WebLogic data source test-ds appears to be available as a service within OSGi:

Service 59 - [weblogic.jdbc.common.internal.RemoteDataSource, javax.sql.DataSource, javax.sql.CommonDataSource, java.sql.Wrapper, weblogic.jdbc.extensions.WLDataSource, java.rmi.Remote, weblogic.jdbc.common.internal.DataSourceMetaData, weblogic.common.resourcepool.ObjectLifeCycle, weblogic.jndi.CrossPartitionAware] (pid: n/a)
  from Bundle 0 - System Bundle (org.apache.felix.framework), version 5.6.0
    Name: test-ds
    service.bundleid: 0
    service.scope: singleton

I've created a persistence bundle com.test.persistence-bundle with the following entity class:

@Entity
public class TestEntity {

    @Id
    private Integer id;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}

... and persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="test-pu" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>osgi:service/test-ds</jta-data-source>
        <non-jta-data-source>osgi:service/test-ds</non-jta-data-source>
        <class>test.model.TestEntity</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
        </properties>
    </persistence-unit>
</persistence>

... and manifest:

Manifest-Version: 1.0
Bnd-LastModified: 1556912147017
Build-Jdk: 1.8.0_171
Built-By: roadkill
Bundle-ManifestVersion: 2
Bundle-Name: test-persistence-bundle
Bundle-SymbolicName: com.test.persistence-bundle
Bundle-Version: 1.0.0.SNAPSHOT
Created-By: Apache Maven Bundle Plugin
DynamicImport-Package: org.hibernate.proxy,javassist.util.proxy
Export-Package: test.model;uses:="javax.persistence";version="1.0.0"
Import-Package: javax.persistence;version="[2.2,3)",org.hibernate.proxy;
 resolution:=optional,javassist.util.proxy;resolution:=optional
Meta-Persistence: META-INF/persistence.xml
Provide-Capability: osgi.service;effective:=active;objectClass="javax.pe
 rsistence.EntityManager";osgi.unit.name=test-pu,osgi.service;effective:
 =active;objectClass="javax.persistence.EntityManagerFactory";osgi.unit.
 name=test-pu,osgi.service;effective:=active;objectClass="org.apache.ari
 es.jpa.template.JpaTemplate";osgi.unit.name=test-pu,osgi.service;effect
 ive:=active;objectClass="org.apache.aries.jpa.supplier.EmSupplier";osgi
 .unit.name=test-pu
Require-Capability: osgi.extender;osgi.extender="aries.jpa",osgi.service
 ;effective:=active;objectClass="javax.persistence.spi.PersistenceProvid
 er";javax.persistence.provider="org.hibernate.jpa.HibernatePersistenceP
 rovider",osgi.service;effective:=active;objectClass="javax.transaction.
 TransactionManager",osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Tool: Bnd-4.2.0.201903051501

I've also created a client bundle com.test.service-impl which implements TestService from another bundle:

@Component(service = TestService.class)
public class TestServiceImpl implements TestService {

    @PersistenceContext(unitName = "test-pu")
    EntityManager em;

    @Override
    public void foo() {
        System.out.println(em);
    }
}

The EntityManager instance should be injected via the blueprint for the service implementation:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">

    <jpa:enable />
    <tx:enable />

    <bean id="testService" class="test.service.impl.TestServiceImpl"/>
    <service ref="testService" interface="test.service.TestService"/>
</blueprint>

However, em is always null. It seems the EntityManager services are never started even though all bundles are Active. I get the following message when updating com.test.service-impl:

13:20:36.380 [Blueprint Extender: 1] INFO org.apache.aries.blueprint.container.BlueprintContainerImpl - Blueprint bundle com.test.service-impl/1.0.0.SNAPSHOT is waiting for dependencies [(&(osgi.unit.name=test-pu)(objectClass=javax.persistence.EntityManager))]
13:20:36.380 [Blueprint Extender: 1] DEBUG org.apache.aries.blueprint.container.BlueprintEventDispatcher - Sending blueprint container event BlueprintEvent[type=GRACE_PERIOD, dependencies=[(&(osgi.unit.name=test-pu)(objectClass=javax.persistence.EntityManager))]] for bundle com.test.service-impl/1.0.0.SNAPSHOT

I'm using Aries JPA to wire everything together with Hibernate as the persistence provider. I also have Aries Blueprint and Aries Transaction installed along with all required dependencies.

Here are the relevant bundles from my bundlelist:

com.test.persistence-api (1.0.0.SNAPSHOT) "test-persistence-api" [active, 23] 
com.test.persistence-bundle (1.0.0.SNAPSHOT) "test-persistence-bundle" [active, 25] 
com.test.service-impl (1.0.0.SNAPSHOT) "test-service-impl" [active, 21] 
javax.persistence-api (2.2) "Java(TM) Persistence API jar" [active, 45] 
javax.transaction-api (1.2) "javax.transaction API" [active, 10] 
javax.transaction-api (1.3) "javax.transaction API" [active, 18] 
org.apache.aries.blueprint.annotation.impl (1.0.1) "Apache Aries Blueprint Annotation Impl" [active, 32] 
org.apache.aries.blueprint.core (1.10.2) "Apache Aries Blueprint Core" [active, 19] 
org.apache.aries.jpa.api (2.7.2) "Apache Aries JPA Container API" [active, 44] 
org.apache.aries.jpa.blueprint (2.7.2) "Apache Aries JPA blueprint" [active, 22] 
org.apache.aries.jpa.container (2.7.2) "Apache Aries JPA container" [active, 64] 
org.apache.aries.jpa.javax.persistence_2.1 (2.7.2) "Apache Aries JPA Specification 2.1 API" [active, 67] 
org.apache.aries.jpa.support (2.7.2) "Apache Aries JPA support" [active, 66] 
org.apache.aries.proxy (1.1.4) "Apache Aries Proxy Service" [active, 70] 
org.apache.aries.transaction.blueprint (2.2.0) "Apache Aries Transaction Blueprint" [active, 52] 
org.apache.aries.transaction.manager (1.3.3) "Apache Aries Transaction Manager" [active, 34] 
org.apache.aries.util (1.1.3) "Apache Aries Util" [active, 30] 
org.hibernate.common.hibernate-commons-annotations (5.1.0.Final) "hibernate-commons-annotations" [active, 56] 
org.hibernate.orm.core (5.3.10.Final) "hibernate-core" [active, 31] 
org.hibernate.orm.core (5.4.2.Final) "hibernate-core" [active, 29] 
org.hibernate.orm.osgi (5.4.2.Final) "hibernate-osgi" [active, 59] 
org.osgi.service.blueprint (1.0.2.201505202024) "org.osgi:org.osgi.service.blueprint" [active, 27] 
org.osgi.service.cm (1.5.0.201505202024) "org.osgi:org.osgi.service.cm" [active, 6] 
org.osgi.service.coordinator (1.0.2.201505202024) "org.osgi:org.osgi.service.coordinator" [active, 73] 
org.osgi.service.jdbc (1.0.0.201505202023) "org.osgi:org.osgi.service.jdbc" [active, 37] 
org.osgi.util.function (1.1.0.201802012106) "org.osgi:org.osgi.util.function" [active, 65] 
org.osgi.util.promise (1.1.1.201810101357) "org.osgi:org.osgi.util.promise" [active, 17] 

Any ideas?

Thanks in advance!


Solution

  • TL;DR: It turns out this was due to a bug in the version of Felix that WebLogic ships with. I was able to upgrade the framework by simply replacing \wlserver\server\lib\org.apache.felix.org.apache.felix.main.jar and \wlserver\server\lib\osgi.jar with the latest versions of felix-main and osgi-core, respectively.


    While trying to figure out the source of the issue, I ended up downloading and manually reading through Karaf's jpa, transaction, and hibernate features to ensure all of the proper bundles were installed and started in the correct order. WebLogic allows you to specify start levels by placing bundles inside of subdirectories within the osgi-lib folder. I'm not sure how helpful this was in the long run, but it gave me some confidence that things were set up in a verified way.

    Here's the list of bundles, with versions and start levels, that I gathered from the Karaf features (not shown: logging/console/shell stuff):

    START LEVEL 100
       ID   State         Level  Name
    [   0] [Active     ] [    0] System Bundle (6.0.3)
    [   1] [Active     ] [   10] Apache Felix Configuration Admin Service (1.9.14)
    [   2] [Active     ] [   11] Apache Felix File Install (3.6.4)
    [   3] [Active     ] [   20] org.objectweb.asm (7.1.0)
    [   4] [Active     ] [   20] org.objectweb.asm.tree.analysis (7.1.0)
    [   5] [Active     ] [   20] org.objectweb.asm.commons (7.1.0)
    [   6] [Active     ] [   20] org.objectweb.asm.tree (7.1.0)
    [   7] [Active     ] [   20] org.objectweb.asm.util (7.1.0)
    [   8] [Active     ] [   20] Apache Aries Blueprint API (1.0.1)
    [   9] [Active     ] [   20] Apache Aries Blueprint CM (1.3.1)
    [  10] [Active     ] [   20] Apache Aries Blueprint Core (1.10.2)
    [  11] [Resolved   ] [   20] Apache Aries Blueprint Core Compatiblity Fragment Bundle (1.0.0)
    [  12] [Active     ] [   20] Apache Aries Proxy Service (1.1.4)
    [  13] [Active     ] [   20] Apache Aries Util (1.1.3)
    [  14] [Active     ] [   30] jaxb-api (2.3.1)
    [  15] [Active     ] [   30] Apache Aries JMX API (1.1.5)
    [  16] [Active     ] [   30] Apache Aries JMX Blueprint API (1.2.0)
    [  17] [Active     ] [   30] Apache Aries JMX Blueprint Core (1.2.0)
    [  18] [Active     ] [   30] Apache Aries JMX Core (1.1.8)
    [  19] [Active     ] [   30] Apache Aries Whiteboard support for JMX DynamicMBean services (1.2.0)
    [  20] [Active     ] [   30] Apache Aries JPA Container API (2.7.2)
    [  21] [Active     ] [   30] Apache Aries JPA blueprint (2.7.2)
    [  22] [Active     ] [   30] Apache Aries JPA container (2.7.2)
    [  23] [Active     ] [   30] Apache Aries JPA support (2.7.2)
    [  24] [Active     ] [   30] Apache ServiceMix :: Specs :: Activation API 1.4 (2.9.0)
    [  25] [Active     ] [    5] Apache Felix EventAdmin (1.5.0)
    [  26] [Active     ] [    5] Apache Felix Metatype Service (1.2.2)
    [  27] [Active     ] [    8] jansi (1.17.1)
    [  31] [Active     ] [   80] Byte Buddy (without dependencies) (1.9.10)
    [  32] [Active     ] [   80] CDI APIs (1.2.0)
    [  33] [Active     ] [   80] ClassMate (1.3.4)
    [  34] [Active     ] [   80] org_dom4j_dom4j_2.1.1_dom4j-2.1.1.jar (0)
    [  36] [Active     ] [   80] geronimo-jta_1.1_spec (1.1.1)
    [  37] [Active     ] [   80] hibernate-commons-annotations (5.1.0.Final)
    [  38] [Active     ] [   80] hibernate-core (5.4.2.Final)
    [  39] [Active     ] [   80] hibernate-osgi (5.4.2.Final)
    [  40] [Active     ] [   80] Java Annotation Indexer (2.0.5.Final)
    [  41] [Active     ] [   80] Javassist (3.24.0.GA)
    [  42] [Active     ] [   80] Expression Language 3.0 API (3.0.0)
    [  43] [Active     ] [   80] javax.interceptor API (1.2)
    [  44] [Active     ] [   80] Java(TM) Persistence API jar (2.2)
    [  45] [Active     ] [   80] Apache Aries JPA Specification 2.1 API (2.7.2)
    [  46] [Active     ] [   80] javax.transaction API (1.2)
    [  47] [Active     ] [   80] JBoss Logging 3 (3.3.2.Final)
    [  48] [Active     ] [   80] Java Transaction API (1.1.1.Final)
    [  49] [Active     ] [   80] Apache Aries Transaction Blueprint (1.1.1)
    [  50] [Active     ] [   80] Apache Aries Transaction Blueprint (2.2.0)
    [  51] [Active     ] [   80] Apache ServiceMix :: Bundles :: javax.inject (1.0.0.2)
    [  52] [Active     ] [   80] org.osgi:org.osgi.service.jdbc (1.0.0.201505202023)
    [  53] [Active     ] [   80] pax-transx-tm-api (0.4.3)
    [  54] [Active     ] [   80] pax-transx-tm-geronimo (0.4.3)
    [  55] [Active     ] [    9] Apache Felix Coordinator Service (1.0.2)
    [  61] [Active     ] [    1] Apache Felix Declarative Services (2.1.16)
    [  65] [Active     ] [    1] org.osgi:org.osgi.util.function (1.1.0.201802012106)
    [  66] [Active     ] [    1] org.osgi:org.osgi.util.promise (1.1.1.201810101357)
    

    I also made some changes to the OSGi framework configuration itself via the WebLogic console:

    • Boot delegation - these were mostly copied from the Karaf configuration, although sun.* and com.sun.* are definitely needed to avoid ClassNotFoundExceptions from bytebuddy:
    com.sun.*, javax.transaction, javax.transaction.*, javax.xml.crypto, javax.xml.crypto.*, jdk.nashorn.*, sun.*, jdk.internal.reflect, jdk.internal.reflect.*
    
    • Init Properties - again, mostly copied from Karaf:
    felix.startlevel.bundle=80
    org.apache.aries.blueprint.synchronous=true
    org.apache.aries.proxy.weaving.disabled=org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.*
    org.apache.aries.proxy.weaving.enabled=none
    org.osgi.framework.startlevel.beginning=100
    

    Lastly, it appears WebLogic sets the name property of the published DataSource service to the JNDI name of the data source itself. Thus, the full value for jta-data-source should be something like:

    osgi:service/javax.sql.DataSource/(name=test-ds)
    

    Hope this helps.