Search code examples
javamavenapache-camelosgiapache-karaf

Apache Camel project not detecting JDBC Driver when deployed on Apache Karaf


I am working on a project where I use a camel route (Camel-sql) to fetch data from a MariaDB database. I use apache commons dbcp2 as a Datasource in my blueprint file. It works perfectly fine when I use mvn:camel-run to run the project in development.

The problem starts when I try to deploy this project on Karaf. mvn:install generates the required jar with blueprint files and manifest file correctly formed. I copy this over to the deploy folder in Karaf.

The bundle installation is successful. But it does not start. I get an exception saying that the bundle was not able to detect the MariaDB java client. This does not make sense to me because I have it installed (using bundle:install -s mvn:...) on Karaf. I did this for all other dependencies like fasterxml, dbcp2 etc.

My requirement is strict: I need to be able to define the data source in my blueprint file. I have found some solutions about using pax-jdbc but did not get anything clear as of yet. Attaching all relevant hints below.

Exception trace

17:39:01.404 WARN [Camel (dbOps-context-g3) thread #10 - timer://foo] Error processing exchange. Exchange[AA8CB8C488B457B-0000000000000005]. Caused by: [org.springframework.jdbc.CannotGetJdbcConnectionException - Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.mariadb.jdbc.Driver']
org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Cannot load JDBC driver class 'org.mariadb.jdbc.Driver'
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:83) ~[!/:?]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:646) ~[!/:?]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:685) ~[!/:?]
    at org.apache.camel.component.sql.SqlProducer.processInternal(SqlProducer.java:145) ~[!/:3.19.0]
    at org.apache.camel.component.sql.SqlProducer.process(SqlProducer.java:132) ~[!/:3.19.0]
    at org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:66) ~[?:?]
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:172) ~[?:?]
    at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:477) ~[?:?]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:181) ~[?:?]
    at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59) ~[?:?]
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:175) ~[?:?]
    at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:392) ~[?:?]
    at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:210) ~[?:?]
    at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76) ~[?:?]
    at java.util.TimerThread.mainLoop(Timer.java:556) ~[?:?]
    at java.util.TimerThread.run(Timer.java:506) ~[?:?]
Caused by: java.sql.SQLException: Cannot load JDBC driver class 'org.mariadb.jdbc.Driver'
    at org.apache.commons.dbcp2.DriverFactory.createDriver(DriverFactory.java:54) ~[!/:2.9.0]
    at org.apache.commons.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:459) ~[!/:2.9.0]
    at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:525) ~[!/:2.9.0]
    at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:731) ~[!/:2.9.0]
    at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:159) ~[!/:?]
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:117) ~[!/:?]
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80) ~[!/:?]
    ... 15 more

Karaf Bundles list

karaf@root()> bundle:list
START LEVEL 100 , List Threshold: 50
 ID │ State    │ Lvl │ Version        │ Name
────┼──────────┼─────┼────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 32 │ Active   │  80 │ 4.4.1          │ Apache Karaf :: OSGi Services :: Event
 59 │ Active   │  50 │ 3.19.0         │ camel-api
 60 │ Active   │  50 │ 3.19.0         │ camel-base
 61 │ Active   │  50 │ 3.19.0         │ camel-base-engine
 62 │ Active   │  50 │ 3.19.0         │ camel-bean
 63 │ Active   │  50 │ 3.19.0         │ camel-browse
 64 │ Active   │  50 │ 3.19.0         │ camel-cloud
 65 │ Active   │  50 │ 3.19.0         │ camel-cluster
 66 │ Active   │  50 │ 3.19.0         │ camel-console
 67 │ Active   │  50 │ 3.19.0         │ camel-controlbus
 68 │ Active   │  50 │ 3.19.0         │ camel-core-catalog
 69 │ Active   │  50 │ 3.19.0         │ camel-core-engine
 70 │ Active   │  50 │ 3.19.0         │ camel-core-languages
 71 │ Active   │  50 │ 3.19.0         │ camel-core-model
 72 │ Active   │  50 │ 3.19.0         │ camel-core-processor
 73 │ Active   │  50 │ 3.19.0         │ camel-core-reifier
 74 │ Active   │  50 │ 3.19.0         │ camel-core-xml
 75 │ Active   │  50 │ 3.19.0         │ camel-dataformat
 76 │ Active   │  50 │ 3.19.0         │ camel-dataset
 77 │ Active   │  50 │ 3.19.0         │ camel-direct
 78 │ Active   │  50 │ 3.19.0         │ camel-directvm
 79 │ Active   │  50 │ 3.19.0         │ camel-file
 80 │ Active   │  50 │ 3.19.0         │ camel-health
 81 │ Active   │  50 │ 3.19.0         │ camel-language
 82 │ Active   │  50 │ 3.19.0         │ camel-log
 83 │ Active   │  50 │ 3.19.0         │ camel-main
 84 │ Active   │  50 │ 3.19.0         │ camel-management
 85 │ Active   │  50 │ 3.19.0         │ camel-management-api
 86 │ Active   │  50 │ 3.19.0         │ camel-mock
 87 │ Active   │  50 │ 3.19.0         │ camel-ref
 88 │ Active   │  50 │ 3.19.0         │ camel-rest
 89 │ Active   │  50 │ 3.19.0         │ camel-saga
 90 │ Active   │  50 │ 3.19.0         │ camel-scheduler
 91 │ Active   │  50 │ 3.19.0         │ camel-seda
 92 │ Active   │  50 │ 3.19.0         │ camel-stub
 93 │ Active   │  50 │ 3.19.0         │ camel-support
 94 │ Active   │  50 │ 3.19.0         │ camel-timer
 95 │ Active   │  50 │ 3.19.0         │ camel-tooling-model
 96 │ Active   │  50 │ 3.19.0         │ camel-util
 97 │ Active   │  50 │ 3.19.0         │ camel-util-json
 98 │ Active   │  50 │ 3.19.0         │ camel-validator
 99 │ Active   │  50 │ 3.19.0         │ camel-vm
100 │ Active   │  50 │ 3.19.0         │ camel-xml-io-util
101 │ Active   │  50 │ 3.19.0         │ camel-xml-jaxb
102 │ Active   │  50 │ 3.19.0         │ camel-xml-jaxp
103 │ Active   │  50 │ 3.19.0         │ camel-xpath
104 │ Active   │  50 │ 3.19.0         │ camel-xslt
105 │ Active   │  50 │ 3.19.0         │ camel-blueprint
106 │ Active   │  80 │ 3.19.0         │ camel-commands-core
107 │ Active   │  50 │ 3.19.0         │ camel-core-osgi
108 │ Active   │  80 │ 3.19.0         │ camel-karaf-commands
120 │ Active   │  50 │ 3.1.1.SNAPSHOT │ com.github.ben-manes.caffeine
121 │ Active   │  50 │ 3.19.0         │ camel-sql
146 │ Active   │  80 │ 2.13.0         │ Jackson-annotations
147 │ Active   │  80 │ 2.13.0         │ Jackson-core
148 │ Active   │  80 │ 2.13.0         │ jackson-databind
155 │ Active   │  80 │ 2.9.0          │ Apache Commons DBCP
156 │ Active   │  80 │ 2.9.0          │ Apache Commons Pool
159 │ Active   │  50 │ 3.19.0         │ camel-paho
160 │ Active   │  50 │ 1.2.5          │ org.eclipse.paho.client.mqttv3
177 │ Resolved │  80 │ 1.0.0.SNAPSHOT │ camel-jdbc-to-mqtt

Data source section from blueprint.xml

    <bean id="dataSourceBean" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
        <property name="url" value="jdbc:mariadb://localhost:3306/test-db"/>
        <property name="username" value="demouser"/>
        <property name="password" value="1demo1"/>
    </bean>

Dependencies and plugins from POM

  <dependencyManagement>
    <dependencies>
      <!-- Camel BOM -->
      <dependency>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-bom</artifactId>
        <version>3.19.0</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
      <dependency>
         <groupId>org.apache.camel.karaf</groupId>
         <artifactId>camel-karaf-bom</artifactId>
         <version>3.19.0</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>

    <!-- DB connectivity -->
    <dependency>
      <groupId>org.mariadb.jdbc</groupId>
      <artifactId>mariadb-java-client</artifactId>
      <version>3.0.8</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>2.9.0</version>
    </dependency>

    <!-- Camel -->
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-core</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-sql</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.karaf</groupId>
      <artifactId>camel-blueprint</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.karaf</groupId>
      <artifactId>camel-blueprint-main</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-paho</artifactId>
    </dependency>

    <!-- Testing -->
    <dependency>
      <groupId>org.apache.camel.karaf</groupId>
      <artifactId>camel-test-blueprint</artifactId>
      <scope>test</scope>
    </dependency>
    
    <!-- logging -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <scope>runtime</scope>
    </dependency>

    <!-- JSON processing -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.13.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>

      <!-- compiler plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>

      <!-- to generate the MANIFEST.MF of the bundle -->
      <plugin>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-bundle-plugin</artifactId>
        <version>3.19.0</version>
        <extensions>false</extensions>
        <executions>
          <execution>
            <id>bundle-manifest</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>manifest</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <!-- to include MANIFEST.MF in the bundle -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
          <archive>
            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
          </archive>
        </configuration>
      </plugin>

      <!-- to run the example using mvn camel-karaf:run -->
      <plugin>
        <groupId>org.apache.camel.karaf</groupId>
        <artifactId>camel-karaf-maven-plugin</artifactId>
        <version>3.19.0</version>
      </plugin>
    </plugins>
  </build>


Solution

  • You need to install the driver inside karaf, the reason your route do not start up is because does not find the driver for your data source.

    Install the driver like

    bundle:install -s mvn:org.mariadb.jdbc/mariadb-java-client:3.0.8
    

    Then enable the resulting bundle as dynamic import like

    bundle:dynamic-import ${bundleId}
    

    May be it should be necessary to enable dynamic import to your route.

    Then restart your route and it should work!

    hope this helps