hibernatemavenjpaosgipax-exam

Using JPA/Hibernate within PaxExam / OSGI Container


I have been successful in getting JPA/Hibernate to work, by following Christian Schneider's tutorial: http://liquid-reality.de/display/liquid/2012/01/13/Apache+Karaf+Tutorial+Part+6+-+Database+Access

But this involves creating a "file named etc/org.ops4j.datasource-tasklist.cfg with the following content:"

osgi.jdbc.driver.name=H2-pool-xa
url=jdbc:h2:mem:person
dataSourceName=person

This clearly will not work when running PaxExam using an OSGI Container.

In addition, I'd rather not add environment-specific data source parameters in either the blueprint.xml or persistence.xml files, as that would subsequently require these files to be modified as code is run in different environments.

As such, there must be a way to spin up a data source from within the test class invoked by JUnit/PaxExam, either within the config() method or somewhere else?

So the question is:

Some project details, my test class is given as follows:

package info.xyz.playground.test.osgi;

import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import info.xyz.playground.core.service.Calculator;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class PlaygroundOsgiTestClient
{
    @Inject
    private BundleContext _bundleContext;

    @Inject
    protected Calculator _calculator;


    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe)
    {
        System.out.println("TestProbeBuilder gets called");
        probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.playground.core.service");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.playground.core.service.impl");
        return probe;
    }


    @Configuration
    public Option[] config()
    {
        return new Option[] {
                junitBundles(),

                // Aries
                mavenBundle().groupId("org.apache.aries").artifactId("org.apache.aries.util").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.api").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.impl").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.api").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.cm").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core").versionAsInProject(),
                mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core.compatibility").versionAsInProject().noStart(),

                // Hibernate and its dependencies
                mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.antlr").versionAsInProject().noStart(),
                mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").versionAsInProject().noStart(),
                mavenBundle().groupId("org.hibernate.javax.persistence").artifactId("hibernate-jpa-2.1-api").versionAsInProject().noStart(),
                mavenBundle().groupId("org.javassist").artifactId("javassist").versionAsInProject().noStart(),
                mavenBundle().groupId("org.jboss").artifactId("jandex").versionAsInProject().noStart(),
                mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.dom4j").versionAsInProject().noStart(),
                mavenBundle().groupId("org.hibernate.common").artifactId("hibernate-commons-annotations").versionAsInProject().noStart(),
                mavenBundle().groupId("org.hibernate").artifactId("hibernate-core").versionAsInProject().noStart(),
                mavenBundle().groupId("org.hibernate").artifactId("hibernate-entitymanager").versionAsInProject().noStart(),
                mavenBundle().groupId("org.apache.geronimo.specs").artifactId("geronimo-jta_1.1_spec").versionAsInProject().noStart(),
                mavenBundle().groupId("org.hibernate").artifactId("hibernate-osgi").versionAsInProject().noStart(),

                // platform
                mavenBundle().groupId("info.xyz.playground").artifactId("xyz-playground-core").versionAsInProject(),
        };
    }


    @Test
    public void testOne()
    {
        // TODO invoke service to perform database operation
    }

}

The blueprint.xml file is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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"

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

    <bean id="calculatorService" class="info.xyz.playground.core.service.impl.CalculatorImpl" />
    <service ref="calculatorService" interface="info.xyz.playground.core.service.Calculator" />

</blueprint>

The persistence.xml file is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/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_1.xsd">

    <persistence-unit name="Playground" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>osgi:service/Playground</jta-data-source>
        <class>info.xyz.playground.core.data.Thing</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
        </properties>
    </persistence-unit>

</persistence>

The pom.xml file from my test project is as follows:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.xyz.playground</groupId>
    <artifactId>xyz-playground-test-osgi</artifactId>
    <version>0.0.1</version>

    <parent>
        <groupId>info.xyz.playground</groupId>
        <artifactId>xyz-playground</artifactId>
        <version>0.0.1</version>
        <relativePath>../xyz-playground</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-container-native</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-junit4</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-link-mvn</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.url</groupId>
            <artifactId>pax-url-aether</artifactId>
            <version>${pax.url.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-inject</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.aries</groupId>
            <artifactId>org.apache.aries.util</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.proxy</groupId>
            <artifactId>org.apache.aries.proxy.api</artifactId>
            <version>1.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.proxy</groupId>
            <artifactId>org.apache.aries.proxy.impl</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.blueprint</groupId>
            <artifactId>org.apache.aries.blueprint.api</artifactId>
            <version>1.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.blueprint</groupId>
            <artifactId>org.apache.aries.blueprint.core</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.blueprint</groupId>
            <artifactId>org.apache.aries.blueprint.core.compatibility</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.aries.blueprint</groupId>
            <artifactId>org.apache.aries.blueprint.cm</artifactId>
            <version>1.0.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.framework</artifactId>
            <version>5.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>${javax.inject.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Testing target -->
        <dependency>
            <groupId>info.xyz.playground</groupId>
            <artifactId>xyz-playground-core</artifactId>
            <version>0.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Needed if you use versionAsInProject() -->
            <plugin>
                <groupId>org.apache.servicemix.tooling</groupId>
                <artifactId>depends-maven-plugin</artifactId>
                <version>1.3.1</version>
                <executions>
                    <execution>
                        <id>generate-depends-file</id>
                        <goals>
                            <goal>generate-depends-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Solution

  • You can use the same approach as the aries itests. Inject the ConfigurationAdmin and create a config in the @Before method.