Search code examples
osgimariadbapache-karafkarafhikaricp

Apache Karaf - How to define XA data source for MariaDB?


We're trying to setup MariaDB data source with HikariCP as conn. pool in Apache Karaf 4.1.2.

These are the features installed:

karaf@root()> feature:install jndi transaction pax-jdbc-pool-hikaricp pax-jdbc-mariadb jasypt-encryption

If we use only the (non-XA) DataSource service definition in blueprint.xml, everything works fine and we can see DataSource (and DataSourceFactory) instance created with no problem:

karaf@root()> service:list DataSource
[javax.sql.DataSource]
----------------------
 datasource.name = MySQL
 osgi.jndi.service.name = jdbc/testdb
 osgi.service.blueprint.compname = dataSource
 service.bundleid = 79
 service.id = 147
 service.scope = bundle
Provided by : 
 Test MariaDB Datasource Bundle (79)

But if we use XADataSource in the blueprint.xml, no DataSource is created (service:list DataSource returns empty)

These are the configuration files we use in the datasource bundle:

datasource.cfg:

db.server = DB_SERVER_IP:3306
db.database = testdb
db.username = root
db.password = ENC(sZwyfHzdvZSVoDDeU2/Vnw==)

blueprint.xml:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:enc="http://karaf.apache.org/xmlns/jasypt/v1.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-activation="eager"
xsi:schemaLocation="
             http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
             http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
     ">

<cm:property-placeholder persistent-id="datasource"
    update-strategy="reload">
</cm:property-placeholder>

<enc:property-placeholder>
    <enc:encryptor class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="config">
            <bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
                <property name="algorithm" value="PBEWITHMD5ANDTRIPLEDES" />
                <property name="password" value="DB_ENC_PWD" />
            </bean>
        </property>
    </enc:encryptor>
</enc:property-placeholder>

<!-- This works just fine! -->
<service ref="dataSource" interface="javax.sql.DataSource">
    <service-properties>
        <entry key="osgi.jndi.service.name" value="jdbc/testdb" />
        <entry key="datasource.name" value="MySQL" />
    </service-properties>
</service>

<!-- But if we use this one, no DataSource is created... -->
<service ref="dataSource" interface="javax.sql.XADataSource">
    <service-properties>
        <entry key="osgi.jndi.service.name" value="jdbc/testdbxa" />
        <entry key="datasource.name" value="MySQL" />
    </service-properties>
</service>

<bean id="dataSource" class="org.mariadb.jdbc.MariaDbDataSource">
    <property name="databaseName" value="${db.database}" />
    <property name="url"
        value="jdbc:mariadb://${db.server}/${db.database}?characterEncoding=UTF-8" />
    <property name="user" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

</blueprint>

I know org.mariadb.jdbc.MariaDbDataSource also implements XADataSource, so this configuration should have been working just fine.

What am I missing here? Are there any missing features that needed to be installed or is this configuration completely wrong?

Thanks in advance.


Solution

  • Finally, I figured it out thanks to C. Schneider's guidance.

    The first mistake I made was to use HikariCP. According to this post, HikariCP does not support XA Connections yet. So I have to switch to DBCP2.

    As it is clearly explained in the comments, using pax-jdbc-config was more understandable and clear way to define a DataSource. So I followed this documentation and, instead of a DataSource bundle (the blueprint way), just created this config file:

    osgi.jdbc.driver.class = org.mariadb.jdbc.Driver
    osgi.jdbc.driver.name=mariadb
    pool=dbcp2
    xa=true
    databaseName=testdb
    user=root
    password=1
    url=jdbc:mariadb://DB_SERVER_IP/testdb?characterEncoding=UTF-8
    dataSourceName=testdb