简体   繁体   中英

Bundle on service mix: org.sqlite.JDBC not found

I have app that is working with SQLite databse. I packed it as a bundle and i can see the services on service mix. When i am sending request to Post or Get service i am receiving this error:

java.lang.ClassNotFoundException: org.sqlite.JDBC not found

I installed SQLite JDBC driver on servicemix but still error.

This is my POM:

<modelVersion>4.0.0</modelVersion>

<groupId>asd</groupId>
<artifactId>name</artifactId>
<version>0.0.1-SNAPSHOT</version>

<packaging>bundle</packaging>
<name>Name</name>
<description>Bundle Desc</description>

<dependencies>
    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.15.1</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-core</artifactId>
        <version>3.1.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.1.5</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <version>3.3.0</version>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                    <Bundle-Description>${project.description}</Bundle-Description>
                    <Import-Package>
                        javax.jws,
                        javax.wsdl,
                        javax.xml.namespace,
                        org.apache.cxf.helpers,
                        org.osgi.service.blueprint,
                        org.xerial.sqlite-jdbc,
                        *
                    </Import-Package>
                    <Export-Package>
                        my.services.package,
                        org.xerial.sqlite-jdbc
                    </Export-Package>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

I have tried to put this org.xerial.sqlite-jdbc only as a Export package and only as an Import package but did not succeeded.

This is the java code for SQLite connection:

private void getConnection() throws ClassNotFoundException, SQLException {
    Class.forName("org.sqlite.JDBC");
    con = DriverManager.getConnection("jdbc:sqlite:SQLiteTest1.db");
    initialise();
}

The app works locally but not on the servicemix.

Your java code is not suitable for OSGi. By default in OSGi each class is loaded by the classloader of the bundle where it is located.

So your own class is loaded by the classloader of your bundle. As you have an Import-Package statement for org.sqlite your code can access the sqlite driver classes.

The problem is that DriverManager loads the classes itself. DriverManager is provided by the system bundle (felix framework bundle). This bundle of course has no Import-Package for the sqllite. So it can not load this class.

There is a simple workaround though. DriverManager allows you to set a thread context classloader. You can set this classloader to the classloader of your own bundle. This way DriverManager can see the sqllite classes. This is only a workaround though.

In OSGi the beast way to avoid problems is to simply not load any classes directly. In the case of jdbc this can be done by using DataSource classes intead of the DriverManager. See this post .

Another option is to use pax-jdbc. It allows to create DataSource services from config. This way you can make your bundle independent of the actual DB driver and still avoid manual class loading. See this example .

You can try like this:

private void getConnection() throws ClassNotFoundException, SQLException {
  SQLiteDataSource ds = new SQLiteDataSource();
  ds.setUrl("jdbc:sqlite:SQLiteTest1.db");
  try {
   con = ds.getConnection();
   System.out.println("Connected.");
  } catch (Exception e) {
   e.printStackTrace();
  }
  initialise();
 }

According to @Christian Schneider this can be done by using DataSource.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM