服务组合捆绑:org.sqlite.JDBC 未找到
Bundle on service mix: org.sqlite.JDBC not found
我有使用 SQLite 数据库的应用程序。
我把它打包成一个包,我可以看到服务组合上的服务。
当我向 Post 发送请求或获取服务时,我收到此错误:
java.lang.ClassNotFoundException: org.sqlite.JDBC 未找到
我在 servicemix 上安装了 SQLite JDBC 驱动程序,但仍然出错。
这是我的 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>
我曾尝试将此 org.xerial.sqlite-jdbc 仅作为导出包和导入包但没有成功。
这是 SQLite 连接的 java 代码:
private void getConnection() throws ClassNotFoundException, SQLException {
Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:SQLiteTest1.db");
initialise();
}
该应用程序可以在本地运行,但不能在 servicemix 上运行。
您的 java 代码不适合 OSGi。默认情况下,在 OSGi 中,每个 class 都由它所在的包的 classloader 加载。
所以你自己的 class 是由你的包的 classloader 加载的。由于您有 org.sqlite 的 Import-Package 语句,因此您的代码可以访问 sqlite 驱动程序 classes。
问题是 DriverManager 加载 classes 本身。 DriverManager 由系统包(felix framework bundle)提供。这个包当然没有用于 sqllite 的 Import-Package。所以它无法加载这个 class.
虽然有一个简单的解决方法。 DriverManager 允许您设置线程上下文 classloader。您可以将此 classloader 设置为您自己的包的 classloader。这样 DriverManager 就可以看到 sqllite classes。不过,这只是一种解决方法。
在 OSGi 中,避免问题的最好方法就是不直接加载任何 classes。在 jdbc 的情况下,这可以通过使用 DataSource classes 而不是 DriverManager 来完成。参见 this post。
另一种选择是使用 pax-jdbc。它允许从配置创建数据源服务。这样你就可以让你的包独立于实际的数据库驱动程序并且仍然避免手动 class 加载。 See this example.
你可以这样试试:
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();
}
根据@Christian Schneider 的说法,这可以通过使用 DataSource 来完成。
我有使用 SQLite 数据库的应用程序。 我把它打包成一个包,我可以看到服务组合上的服务。 当我向 Post 发送请求或获取服务时,我收到此错误:
java.lang.ClassNotFoundException: org.sqlite.JDBC 未找到
我在 servicemix 上安装了 SQLite JDBC 驱动程序,但仍然出错。
这是我的 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>
我曾尝试将此 org.xerial.sqlite-jdbc 仅作为导出包和导入包但没有成功。
这是 SQLite 连接的 java 代码:
private void getConnection() throws ClassNotFoundException, SQLException {
Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:SQLiteTest1.db");
initialise();
}
该应用程序可以在本地运行,但不能在 servicemix 上运行。
您的 java 代码不适合 OSGi。默认情况下,在 OSGi 中,每个 class 都由它所在的包的 classloader 加载。
所以你自己的 class 是由你的包的 classloader 加载的。由于您有 org.sqlite 的 Import-Package 语句,因此您的代码可以访问 sqlite 驱动程序 classes。
问题是 DriverManager 加载 classes 本身。 DriverManager 由系统包(felix framework bundle)提供。这个包当然没有用于 sqllite 的 Import-Package。所以它无法加载这个 class.
虽然有一个简单的解决方法。 DriverManager 允许您设置线程上下文 classloader。您可以将此 classloader 设置为您自己的包的 classloader。这样 DriverManager 就可以看到 sqllite classes。不过,这只是一种解决方法。
在 OSGi 中,避免问题的最好方法就是不直接加载任何 classes。在 jdbc 的情况下,这可以通过使用 DataSource classes 而不是 DriverManager 来完成。参见 this post。
另一种选择是使用 pax-jdbc。它允许从配置创建数据源服务。这样你就可以让你的包独立于实际的数据库驱动程序并且仍然避免手动 class 加载。 See this example.
你可以这样试试:
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();
}
根据@Christian Schneider 的说法,这可以通过使用 DataSource 来完成。