6.4. OSGi JDBC 서비스 사용
OSGi Enterprise R6 사양의 125장에서는 org.osgi.service.jdbc 패키지에서 단일 인터페이스를 정의합니다. 다음은 OSGi에서 데이터 소스를 처리하는 방법입니다.
public interface DataSourceFactory {
java.sql.Driver createDriver(Properties props);
javax.sql.DataSource createDataSource(Properties props);
javax.sql.ConnectionPoolDataSource createConnectionPoolDataSource(Properties props);
javax.sql.XADataSource createXADataSource(Properties props);
}
앞서 언급했듯이 일반 java.sql.Connection 연결은 java.sql.Driver 에서 직접 가져올 수 있습니다.
Generic org.osgi.service.jdbc.DataSourceFactory
org.osgi.service.jdbc.DataSourceFactory 의 가장 간단한 구현은 org.ops4j.pax.jdbc.impl.DriverDataSourceFactory 입니다. mvn:org.ops4j.pax.jdbc/pax-jdbc/pax-jdbc/1.3.0 번들이 제공하는 org.ops4j.impl.DriverDataSourceFactory입니다. 이 모든 작업은 표준 Java™ ServiceLoader 유틸리티에 대한 /META-INF/services/java.sql.Driver 설명자를 포함할 수 있는 번들을 추적하는 것입니다. 표준 JDBC 드라이버를 설치하는 경우 pax-jdbc 번들은 java.sql.Driver.connect() 호출을 통해 연결을 가져오기 위해 (직접은 아님) DataSourceFactory 를 등록합니다.
karaf@root()> install -s mvn:org.osgi/org.osgi.service.jdbc/1.0.0 Bundle ID: 223 karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc/1.3.0 Bundle ID: 224 karaf@root()> install -s mvn:org.postgresql/postgresql/42.2.5 Bundle ID: 225 karaf@root()> install -s mvn:mysql/mysql-connector-java/5.1.34 Bundle ID: 226 karaf@root()> bundle:services -p org.postgresql.jdbc42 PostgreSQL JDBC Driver JDBC42 (225) provides: --------------------------------------------- objectClass = [org.osgi.service.jdbc.DataSourceFactory] osgi.jdbc.driver.class = org.postgresql.Driver osgi.jdbc.driver.name = PostgreSQL JDBC Driver osgi.jdbc.driver.version = 42.2.5 service.bundleid = 225 service.id = 242 service.scope = singleton karaf@root()> bundle:services -p com.mysql.jdbc Oracle Corporation's JDBC Driver for MySQL (226) provides: ---------------------------------------------------------- objectClass = [org.osgi.service.jdbc.DataSourceFactory] osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = com.mysql.jdbc osgi.jdbc.driver.version = 5.1.34 service.bundleid = 226 service.id = 243 service.scope = singleton ----- objectClass = [org.osgi.service.jdbc.DataSourceFactory] osgi.jdbc.driver.class = com.mysql.fabric.jdbc.FabricMySQLDriver osgi.jdbc.driver.name = com.mysql.jdbc osgi.jdbc.driver.version = 5.1.34 service.bundleid = 226 service.id = 244 service.scope = singleton karaf@root()> service:list org.osgi.service.jdbc.DataSourceFactory [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = org.postgresql.Driver osgi.jdbc.driver.name = PostgreSQL JDBC Driver osgi.jdbc.driver.version = 42.2.5 service.bundleid = 225 service.id = 242 service.scope = singleton Provided by : PostgreSQL JDBC Driver JDBC42 (225) [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = com.mysql.jdbc osgi.jdbc.driver.version = 5.1.34 service.bundleid = 226 service.id = 243 service.scope = singleton Provided by : Oracle Corporation's JDBC Driver for MySQL (226) [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = com.mysql.fabric.jdbc.FabricMySQLDriver osgi.jdbc.driver.name = com.mysql.jdbc osgi.jdbc.driver.version = 5.1.34 service.bundleid = 226 service.id = 244 service.scope = singleton Provided by : Oracle Corporation's JDBC Driver for MySQL (226)
위의 명령을 사용하면 javax.sql.DataSource 서비스가 아직 등록되지 않았지만 한 발짝 더 가깝습니다. 위의 중간 org.osgi.service.jdbc.DataSourceFactory 서비스를 사용하여 다음을 얻을 수 있습니다.
-
java.sql.Driver -
속성을 전달하여
javax.sql.DataSource:url,user및password를createDataSource()메서드에 전달합니다.
일반 org sql.XADataSource를 가져올 수 없습니다. .osgi.service.jdbc.DataFactory에서 또는 javax.javax.sql.XADataSource
mvn:org.postgresql/postgresql/42.2.5 번들은 OSGi JDBC 사양을 올바르게 구현하고 org.osgi.service.jdbc.DataSourceFactory 인스턴스를 XA 및 ConnectionPool 데이터 소스를 생성하는 것을 포함하여 구현되는 모든 메서드에 등록합니다.
전용 데이터베이스별 org.osgi.service.jdbc.DataSourceFactory 구현
다음과 같은 추가 번들이 있습니다.
-
mvn:org.ops4j.pax.jdbc/pax-jdbc-mysql/1.3.0 -
mvn:org.ops4j.pax.jdbc/pax-jdbc-db2/1.3.0 - …
이러한 번들은 javax.sql .DataSourcey 서비스를 등록합니다. 예를 들면 다음과 같습니다.
.ConnectionPoolDataSource 및 javax.sql.XADataSource 를 포함하여 모든 종류의 팩토리 를 반환할 수 있는 데이터베이스별 org.osgi.service.jdbc
karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-mysql/1.3.0 Bundle ID: 227 karaf@root()> bundle:services -p org.ops4j.pax.jdbc.mysql OPS4J Pax JDBC MySQL Driver Adapter (227) provides: --------------------------------------------------- objectClass = [org.osgi.service.jdbc.DataSourceFactory] osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = mysql service.bundleid = 227 service.id = 245 service.scope = singleton karaf@root()> service:list org.osgi.service.jdbc.DataSourceFactory ... [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = mysql service.bundleid = 227 service.id = 245 service.scope = singleton Provided by : OPS4J Pax JDBC MySQL Driver Adapter (227)
6.4.1. PAX-JDBC 구성 서비스
pax-jdbc (또는 pax-jdbc-mysql,pax-jdbc-oracle, …) 번들을 사용하면 org.osgi.service.jdbc.DataSourceFactory 서비스가 등록되어 지정된 데이터베이스의 데이터 소스를 가져올 수 있습니다( 6.2.1절. “데이터베이스 특정 및 일반 데이터 소스”참조). 그러나 실제 데이터 소스는 아직 없습니다.
mvn:org.ops4j.pax.jdbc/pax-jdbc-config/1.3.0 번들은 다음 두 가지 작업을 수행하는 관리형 서비스 팩토리를 제공합니다.
메서드를 호출하기 위해
org.osgi.service.jdbc.DataSourceFactoryOSGi 서비스를 추적합니다.public DataSource createDataSource(Properties props); public XADataSource createXADataSource(Properties props); public ConnectionPoolDataSource createConnectionPoolDataSource(Properties props);
-
위의 방법에 필요한 속성을 수집하기 위해
org.ops4j.datasource팩토리 PID 를 추적합니다. 예를 들어${karaf.etc}/org.ops4j.datasource-mysql.cfg파일을 생성하여 구성 관리 서비스에 사용할 수 있는 방법을 사용하여 팩토리 구성을 생성하는 경우 최종 단계를 수행하여 실제 데이터베이스별 데이터 소스를 노출할 수 있습니다.
다음은 새로운 Fuse 설치부터 시작하기위한 상세한 표준 단계별 가이드입니다.
필요한 번들을 정확하게 표시하기 위해 기능 대신 번들을 명시적으로 설치합니다. 편의를 위해 PAX JDBC 프로젝트는 여러 데이터베이스 제품 및 구성 접근 방식에 대한 기능을 제공합니다.
Install a JDBC driver with
/META-INF/services/java.sql.Driver:karaf@root()> install -s mvn:mysql/mysql-connector-java/5.1.34 Bundle ID: 223
중간
org.osgi.service.jdbc.DataSourceFactory를 등록하는 OSGi JDBC 서비스 번들 및pax-jdbc-mysql번들을 설치합니다.karaf@root()> install -s mvn:org.osgi/org.osgi.service.jdbc/1.0.0 Bundle ID: 224 karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-mysql/1.3.0 Bundle ID: 225 karaf@root()> service:list org.osgi.service.jdbc.DataSourceFactory [org.osgi.service.jdbc.DataSourceFactory] ----------------------------------------- osgi.jdbc.driver.class = com.mysql.jdbc.Driver osgi.jdbc.driver.name = mysql service.bundleid = 225 service.id = 242 service.scope = singleton Provided by : OPS4J Pax JDBC MySQL Driver Adapter (225)
org.osgi.service.jdbc.DataSourceFactory서비스 및org.ops4j.datasourcefactory PID 를 추적하는pax-jdbc-config 번 들과pax-jdbc-config번들을 설치합니다.karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc/1.3.0 Bundle ID: 226 karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-pool-common/1.3.0 Bundle ID: 227 karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-config/1.3.0 Bundle ID: 228 karaf@root()> bundle:services -p org.ops4j.pax.jdbc.config OPS4J Pax JDBC Config (228) provides: ------------------------------------- objectClass = [org.osgi.service.cm.ManagedServiceFactory] service.bundleid = 228 service.id = 245 service.pid = org.ops4j.datasource service.scope = singleton
팩토리 구성 을 생성합니다(MySQL 서버가 실행 중이라고 가정).
karaf@root()> config:edit --factory --alias mysql org.ops4j.datasource karaf@root()> config:property-set osgi.jdbc.driver.name mysql karaf@root()> config:property-set dataSourceName mysqlds karaf@root()> config:property-set url jdbc:mysql://localhost:3306/reportdb karaf@root()> config:property-set user fuse karaf@root()> config:property-set password fuse karaf@root()> config:update karaf@root()> config:list '(service.factoryPid=org.ops4j.datasource)' ---------------------------------------------------------------- Pid: org.ops4j.datasource.a7941498-9b62-4ed7-94f3-8c7ac9365313 FactoryPid: org.ops4j.datasource BundleLocation: ? Properties: dataSourceName = mysqlds felix.fileinstall.filename = file:${karaf.etc}/org.ops4j.datasource-mysql.cfg osgi.jdbc.driver.name = mysql password = fuse service.factoryPid = org.ops4j.datasource service.pid = org.ops4j.datasource.a7941498-9b62-4ed7-94f3-8c7ac9365313 url = jdbc:mysql://localhost:3306/reportdb user = fusepax-jdbc-config가javax.sql.DataSource서비스로 구성을 처리했는지 확인합니다.karaf@root()> service:list javax.sql.DataSource [javax.sql.DataSource] ---------------------- dataSourceName = mysqlds felix.fileinstall.filename = file:${karaf.etc}/org.ops4j.datasource-mysql.cfg osgi.jdbc.driver.name = mysql osgi.jndi.service.name = mysqlds password = fuse pax.jdbc.managed = true service.bundleid = 228 service.factoryPid = org.ops4j.datasource service.id = 246 service.pid = org.ops4j.datasource.a7941498-9b62-4ed7-94f3-8c7ac9365313 service.scope = singleton url = jdbc:mysql://localhost:3306/reportdb user = fuse Provided by : OPS4J Pax JDBC Config (228)
이제 실제 데이터베이스별(아직 풀링 없음) 데이터 소스가 있습니다. 필요한 곳에 이미 삽입할 수 있습니다. 예를 들어 Karaf 명령을 사용하여 데이터베이스를 쿼리할 수 있습니다.
karaf@root()> feature:install -v jdbc Adding features: jdbc/[4.2.0.fuse-000237-redhat-1,4.2.0.fuse-000237-redhat-1] ... karaf@root()> jdbc:ds-list Mon May 14 08:46:22 CEST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. Name │ Product │ Version │ URL │ Status ────────┼─────────┼─────────┼──────────────────────────────────────┼─────── mysqlds │ MySQL │ 5.7.21 │ jdbc:mysql://localhost:3306/reportdb │ OK karaf@root()> jdbc:query mysqlds 'select * from incident' Mon May 14 08:46:46 CEST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. date │ summary │ name │ details │ id │ email ──────────────────────┼────────────┼────────┼───────────────────────────────┼────┼───────────────── 2018-02-20 08:00:00.0 │ Incident 1 │ User 1 │ This is a report incident 001 │ 1 │ user1@redhat.com 2018-02-20 08:10:00.0 │ Incident 2 │ User 2 │ This is a report incident 002 │ 2 │ user2@redhat.com 2018-02-20 08:20:00.0 │ Incident 3 │ User 3 │ This is a report incident 003 │ 3 │ user3@redhat.com 2018-02-20 08:30:00.0 │ Incident 4 │ User 4 │ This is a report incident 004 │ 4 │ user4@redhat.com
위의 예제에서는 MySQL 경고를 볼 수 있습니다. 이것은 문제가 아닙니다. 모든 속성(OSGi JDBC 특정 속성뿐만 아니라)이 제공될 수 있습니다.
karaf@root()> config:property-set --pid org.ops4j.datasource.a7941498-9b62-4ed7-94f3-8c7ac9365313 useSSL false karaf@root()> jdbc:ds-list Name │ Product │ Version │ URL │ Status ────────┼─────────┼─────────┼──────────────────────────────────────┼─────── mysqlds │ MySQL │ 5.7.21 │ jdbc:mysql://localhost:3306/reportdb │ OK
6.4.2. 처리된 속성 요약
admin 팩토리 PID 구성의 속성은 관련 org.osgi.service.jdbc.DataSourceFactory 구현으로 전달됩니다.
일반
org.ops4j.pax.jdbc.impl.DriverDataSourceFactory properties:
-
url -
user -
암호
DB2
org.ops4j.pax.jdbc.db2.impl.DB2DataSourceFactory 속성에는 다음과 같은 구현 클래스의 모든 empty 속성이 포함됩니다.
-
com.ibm.db2.jcc.DB2SimpleDataSource -
com.ibm.db2.jcc.DB2ConnectionPoolDataSource -
com.ibm.db2.jcc.DB2XADataSource
PostgreSQL
Nnative org.postgresql.osgi.PGDataSourceFactory 속성에는 org.postgresql.PGProperty 에 지정된 모든 속성이 포함됩니다.
HSQLDB
org.ops4j.pax.jdbc.hsqldb.impl.HsqldbDataSourceFactory properties:
-
url -
user -
암호 -
databaseName 모든 Cryostat 속성
-
org.hsqldb.jdbc.JDBCDataSource -
org.hsqldb.jdbc.pool.JDBCPooledDataSource -
org.hsqldb.jdbc.pool.JDBCXADataSource
-
SQL Server 및 Sybase
org.ops4j.pax.jdbc.jtds.jtds.jtds.JTDSDataFactory 속성에는 net.sourceforge.jtds.jdbcx.JtdsDataSource.
SQL Server
org.ops4j.pax.jdbc.mssql.impl.MSSQLDataSourceFactory properties:
-
url -
user -
암호 -
databaseName -
serverName -
portNumber 모든 Cryostat 속성
-
com.microsoft.sqlserver.jdbc.SQLServerDataSource -
com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource -
com.microsoft.sqlserver.jdbc.SQLServerXADataSource
-
MySQL
org.ops4j.pax.jdbc.mysql.impl.MysqlDataSourceFactory properties:
-
url -
user -
암호 -
databaseName -
serverName -
portNumber 모든 Cryostat 속성
-
com.mysql.jdbc.jdbc2.optional.MysqlDataSource -
com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource -
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
-
Oracle
org.ops4j.pax.jdbc.oracle.impl.OracleDataSourceFactory properties:
-
url -
databaseName -
serverName -
user -
암호 모든 Cryostat 속성
-
oracle.jdbc.pool.OracleDataSource -
oracle.jdbc.pool.OracleConnectionPoolDataSource -
oracle.jdbc.xa.client.OracleXADataSource
-
SQLite
org.ops4j.pax.jdbc.sqlite.impl.SqliteDataSourceFactory properties:
-
url -
databaseName -
org.sqlite.SQLiteDataSource의 모든 Cryostat 속성
6.4.3. pax-jdb-config 번들이 속성을 처리하는 방법
pax-jdbc-config 번들은 jdbc 로 접두사가 지정된 속성을 처리합니다. 이러한 모든 속성은 이 접두사가 제거되고 나머지 이름은 전달됩니다.
다음은 Fuse 새로 설치부터 시작하는 예제입니다.
karaf@root()> install -s mvn:mysql/mysql-connector-java/5.1.34
Bundle ID: 223
karaf@root()> install -s mvn:org.osgi/org.osgi.service.jdbc/1.0.0
Bundle ID: 224
karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-mysql/1.3.0
Bundle ID: 225
karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc/1.3.0
Bundle ID: 226
karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-pool-common/1.3.0
Bundle ID: 227
karaf@root()> install -s mvn:org.ops4j.pax.jdbc/pax-jdbc-config/1.3.0
Bundle ID: 228
karaf@root()> config:edit --factory --alias mysql org.ops4j.datasource
karaf@root()> config:property-set osgi.jdbc.driver.name mysql
karaf@root()> config:property-set dataSourceName mysqlds
karaf@root()> config:property-set dataSourceType DataSource
karaf@root()> config:property-set jdbc.url jdbc:mysql://localhost:3306/reportdb
karaf@root()> config:property-set jdbc.user fuse
karaf@root()> config:property-set jdbc.password fuse
karaf@root()> config:property-set jdbc.useSSL false
karaf@root()> config:update
karaf@root()> config:list '(service.factoryPid=org.ops4j.datasource)'
----------------------------------------------------------------
Pid: org.ops4j.datasource.7c3ee718-7309-46a0-ae3a-64b38b17a0a3
FactoryPid: org.ops4j.datasource
BundleLocation: ?
Properties:
dataSourceName = mysqlds
dataSourceType = DataSource
felix.fileinstall.filename = file:/data/servers/7.12.0.fuse-7_12_0-00019-redhat-00001/etc/org.ops4j.datasource-mysql.cfg
jdbc.password = fuse
jdbc.url = jdbc:mysql://localhost:3306/reportdb
jdbc.useSSL = false
jdbc.user = fuse
osgi.jdbc.driver.name = mysql
service.factoryPid = org.ops4j.datasource
service.pid = org.ops4j.datasource.7c3ee718-7309-46a0-ae3a-64b38b17a0a3
karaf@root()> service:list javax.sql.DataSource
[javax.sql.DataSource]
----------------------
dataSourceName = mysqlds
dataSourceType = DataSource
felix.fileinstall.filename = file:${karaf.etc}/org.ops4j.datasource-mysql.cfg
jdbc.password = fuse
jdbc.url = jdbc:mysql://localhost:3306/reportdb
jdbc.user = fuse
jdbc.useSSL = false
osgi.jdbc.driver.name = mysql
osgi.jndi.service.name = mysqlds
pax.jdbc.managed = true
service.bundleid = 228
service.factoryPid = org.ops4j.datasource
service.id = 246
service.pid = org.ops4j.datasource.7c3ee718-7309-46a0-ae3a-64b38b17a0a3
service.scope = singleton
Provided by :
OPS4J Pax JDBC Config (228)
pax-jdbc-config 번들에는 다음과 같은 속성이 필요합니다.
-
osgi.jdbc.driver.name -
dataSourceName -
dataSourceType
관련 org.osgi.service.jdbc.DataSourceFactory 메서드를 찾아서 호출하려면 다음을 수행합니다. jdbc. 접두사가 있는 속성은 ( 접두사를 제거한 후) org.osgi.service.jdbc.DataSourceFactory.createDataSourceSource(properties) 로 전달됩니다. 그러나 이러한 속성은 접두사가 제거되지 않고 (예: javax.sql.DataSource OSGi 서비스) 속성으로 추가됩니다.