125 Data Service Specification for JDBC™ Technology

125.1 Introduction

The Java Database Connectivity (JDBC) standard provides an API for applications to interact with relational database systems from different vendors. To abstract over concrete database systems and vendor specific characteristics, the JDBC specification provides various classes and Service Provider Interfaces (SPI) that can be used for database interaction. Implementations are database specific and provided by the corresponding driver. This specification defines how OSGi-aware JDBC drivers can provide access to their implementations. Applications can rely on this mechanism to transparently access drivers and to stay independent from driver specific classes. Additionally, this mechanism helps to use common OSGi practices and to avoid class loading problems.

This specification uses a number of packages that are defined in Java SE 1.4 or later.

125.1.1 Essentials

  • Registration - Provide a mechanism for JDBC driver announcements.

  • Lookup - Inspect available database drivers and provide means for driver access.

  • Services - Uses a service model for getting the driver objects.

  • Compatible - Minimize the amount of work needed to support this specification for existing drivers.

125.1.2 Entities

  • Relational Database Management Systems - (RDBMS) An external database system.

  • Database Driver - JDBC-compliant database driver that is delivered in a bundle.

  • Data Source Factory - Provides one of the different Data Sources that gives access to a database driver.

  • Application - The application that wants to access a relational database system.

Figure 125.1 JDBC Class/Service Overview

JDBC Class/Service Overview

125.1.3 Dependencies

The classes and interfaces used in this specification come from the following packages:

javax.sql
java.sql

These packages have no associated version. It is assumed they come from the runtime environment. This specification is based on Java SE 1.4 or later.

125.1.4 Synopsis

A JDBC Database Driver is the software that maps the JDBC specification to a specific implementation of a relational database. For OSGi, JDBC drivers are delivered as driver bundles. A driver bundle registers a Data Source Factory service when it is ACTIVE. Service properties are used to specify the database driver name, version, etc. The Data Source Factory service provides methods to create DataSource, ConnectionPoolDataSource, XADataSource, or Driver objects. These objects are then used by an application to interact with the relational database system in the standard way.

The application can query the service registry for available Data Source Factory services. It can select particular drivers by filtering on the service properties. This service based model is easy to use with dependency injection frameworks like Blueprint or Declarative Services.

125.2 Database Driver

A Database Driver provides the connection between an Application and a particular database. A single OSGi Framework can contain several Database Drivers simultaneously. To make itself available to Applications, a Database Driver must register a Data Source Factory service. Applications must be able to find the appropriate Database Driver. The Database Driver must therefore register the Data Source Factory service with the following service properties:

  • OSGI_JDBC_DRIVER_CLASS - (String) The required name of the driver implementation class. This property is the primary key to find a driver's Data Source Factory. It is not required that there is an actual class with this name.

  • OSGI_JDBC_DRIVER_NAME - (String) The optional driver name. This property is informational.

  • OSGI_JDBC_DRIVER_VERSION - (String) The driver version. The version is not required to be an OSGi version, it should be treated as an opaque string. This version is likely not related to the package of the implementation class or its bundle.

The previous properties are vendor-specific and are meant to further describe the Database Driver to the Application.

Each Data Source Factory service must relate to a single Database Driver. The Database Driver implementation bundle does not necessarily need to be the registrar of the Data Source Factory service. Any bundle can provide the Data Source Factory service and delegate to the appropriate driver specific implementation classes. However, as JDBC driver implementations evolve to include built-in support for OSGi they can provide the Data Source Factory service themselves. This implies that the same driver can be registered multiple times.

125.2.1 Life Cycle

A Data Source Factory service should be registered while its Driver Bundle is in the ACTIVE state or when it has a lazy activation policy and is in the STARTING state.

What happens to the objects created by the Data Source Factory service, and the objects they created, is undefined in this specification. Database Drivers are not mandated to track the proper life cycle of these objects.

125.2.2 Package Dependencies

A Database Driver must import the javax.sql package. The java.sql package that contains the Driver and SQLException interface is automatically visible because it starts with java.. Both packages are contained in the JRE since Java SE 1.4. These packages are not normally versioned with OSGi version numbers. Bundles using the Data Source Factory must therefore ensure they get the proper imports, which is usually from the JRE. Due to the lack of specified metadata, the deployer is responsible for ensuring this.

125.3 Applications

125.3.1 Selecting the Data Source Factory Service

Applications can query the OSGi service registry for available Database Drivers by getting a list of Data Source Factory services. Normally, the application needs access to specific drivers that match their needed relational database type. The service properties can be used to find the desired Database Driver. This model is well supported by dependency injection frameworks like Blueprint or Declarative Services. However, it can of course also be used with the basic service methods. The following code shows how a Service Tracker can be used to get a Database Driver called ACME DB.

Filter filter = context.createFilter(
    "(&(objectClass="  + 
        DataSourceFactory.class.getName() + 
    ")(" + 
        DataSourceFactory.OSGI_JDBC_DRIVER_CLASS + "=com.acme.db.Driver))");

ServiceTracker tracker = new ServiceTracker(context, filter, null);
tracker.open();

DataSourceFactory dsf = (DataSourceFactory) tracker.getService();

125.3.2 Using Database Drivers

The Data Source Factory service can be used to obtain instances for the following JDBC related types:

  • javax.sql.DataSource

  • javax.sql.ConnectionPoolDataSource

  • javax.sql.XADataSource

  • java.sql.Driver

Which type of Connection provider that is actually required depends on the Application and the use case. For each type, the Data Source Factory service provides a method that returns the corresponding instance. Each method takes a Properties object as a parameter to pass a configuration to the Database Driver implementation. The configuration is driver-specific and can be used to specify the URL for the database and user credentials. Common property names for these configuration properties are also defined in the DataSourceFactory interface.

A Data Source Factory is not required to implement all of the factory methods. If an implementation does not support a particular type then it must throw a SQL Exception. This specification does not provide a mechanism to depend on a Data Source Factory service that implements a particular factory method.

The following code shows how a DataSource object could be created.

Properties props = new Properties(); 
props.put(DataSourceFactory.JDBC_URL,      "jdbc:acme:ACMEDB"); 
props.put(DataSourceFactory.JDBC_USER,     "foo"); 
props.put(DataSourceFactory.JDBC_PASSWORD, "secret"); 
DataSource dataSource = dsf.createDataSource(props);

The DataSourceFactory interface has several static fields that represent common property keys for the Properties instance. General properties are:

The following additional property keys are provided for applications that want to create a ConnectionPoolDataSource object or a XAPoolDataSource object:

Which property keys and values are supported depends on the driver implementation. Drivers can support additional custom configuration properties.

125.3.3 Using JDBC in OSGi and Containers

The JDBC service provides JDBC driver services, not container services. A typical client would only use the DataSourceFactory.createDataSource() method to procure a regular Data Source from which they can obtain (usually non-pooled) connections.

Containers generally offer connection pools and support XA transactions. The container manages the pools and does this by using Pooled Connection or XA Connection objects from a driver-implemented respective Connection Pool Data Source or XA Data Source. To support containers, frameworks, or any client that wants to manage a pool, these Data Source types are included in the Data Source Factory service. Drivers are permitted to implement their own Data Source using an underlying connection pooling scheme. This is driver-dependent and not related to the OSGi specifications.

The usual set of JDBC properties are defined in the services for use with the Data Source types. They are the same as what is defined for JDBC and the caller should know which properties make sense when passed to a given Data Source type. The same result should occur in OSGi as occurs outside of OSGi. If the driver does not support a given property with a given Data Source type then it can ignore it or it can throw an Exception.

125.4 Security

This specification depends on the JDBC specification for security.

125.5 org.osgi.service.jdbc

Version 1.0

JDBC Service Package Version 1.0.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.jdbc; version="[1.0,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.jdbc; version="[1.0,1.1)"

125.5.1 Summary

125.5.2 public interface DataSourceFactory

A factory for JDBC connection factories. There are 3 preferred connection factories for getting JDBC connections: javax.sql.DataSource, javax.sql.ConnectionPoolDataSource, and javax.sql.XADataSource. DataSource providers should implement this interface and register it as an OSGi service with the JDBC driver class name in the OSGI_JDBC_DRIVER_CLASS property.

Thread-safe

125.5.2.1 public static final String JDBC_DATABASE_NAME = "databaseName"

The "databaseName" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.2 public static final String JDBC_DATASOURCE_NAME = "dataSourceName"

The "dataSourceName" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.3 public static final String JDBC_DESCRIPTION = "description"

The "description" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.4 public static final String JDBC_INITIAL_POOL_SIZE = "initialPoolSize"

The "initialPoolSize" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.5 public static final String JDBC_MAX_IDLE_TIME = "maxIdleTime"

The "maxIdleTime" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.6 public static final String JDBC_MAX_POOL_SIZE = "maxPoolSize"

The "maxPoolSize" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.7 public static final String JDBC_MAX_STATEMENTS = "maxStatements"

The "maxStatements" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.8 public static final String JDBC_MIN_POOL_SIZE = "minPoolSize"

The "minPoolSize" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.9 public static final String JDBC_NETWORK_PROTOCOL = "networkProtocol"

The "networkProtocol" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.10 public static final String JDBC_PASSWORD = "password"

The "password" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.11 public static final String JDBC_PORT_NUMBER = "portNumber"

The "portNumber" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.12 public static final String JDBC_PROPERTY_CYCLE = "propertyCycle"

The "propertyCycle" property that ConnectionPoolDataSource and XADataSource clients may supply a value for when calling createConnectionPoolDataSource(Properties) or createXADataSource(Properties) on drivers that support this property.

125.5.2.13 public static final String JDBC_ROLE_NAME = "roleName"

The "roleName" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.14 public static final String JDBC_SERVER_NAME = "serverName"

The "serverName" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.15 public static final String JDBC_URL = "url"

The "url" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.16 public static final String JDBC_USER = "user"

The "user" property that DataSource clients should supply a value for when calling createDataSource(Properties).

125.5.2.17 public static final String OSGI_JDBC_DRIVER_CLASS = "osgi.jdbc.driver.class"

Service property used by a JDBC driver to declare the driver class when registering a JDBC DataSourceFactory service. Clients may filter or test this property to determine if the driver is suitable, or the desired one.

125.5.2.18 public static final String OSGI_JDBC_DRIVER_NAME = "osgi.jdbc.driver.name"

Service property used by a JDBC driver to declare the driver name when registering a JDBC DataSourceFactory service. Clients may filter or test this property to determine if the driver is suitable, or the desired one.

125.5.2.19 public static final String OSGI_JDBC_DRIVER_VERSION = "osgi.jdbc.driver.version"

Service property used by a JDBC driver to declare the driver version when registering a JDBC DataSourceFactory service. Clients may filter or test this property to determine if the driver is suitable, or the desired one.

125.5.2.20 public ConnectionPoolDataSource createConnectionPoolDataSource(Properties props) throws SQLException

The properties used to configure the ConnectionPoolDataSource. null indicates no properties. If the property cannot be set on the ConnectionPoolDataSource being created then a SQLException must be thrown.

Create a new ConnectionPoolDataSource using the given properties.

A configured ConnectionPoolDataSource.

SQLException– If the ConnectionPoolDataSource cannot be created.

125.5.2.21 public DataSource createDataSource(Properties props) throws SQLException

The properties used to configure the DataSource . null indicates no properties. If the property cannot be set on the DataSource being created then a SQLException must be thrown.

Create a new DataSource using the given properties.

A configured DataSource.

SQLException– If the DataSource cannot be created.

125.5.2.22 public Driver createDriver(Properties props) throws SQLException

The properties used to configure the Driver. null indicates no properties. If the property cannot be set on the Driver being created then a SQLException must be thrown.

Create a new Driver using the given properties.

A configured Driver.

SQLException– If the Driver cannot be created.

125.5.2.23 public XADataSource createXADataSource(Properties props) throws SQLException

The properties used to configure the XADataSource. null indicates no properties. If the property cannot be set on the XADataSource being created then a SQLException must be thrown.

Create a new XADataSource using the given properties.

A configured XADataSource.

SQLException– If the XADataSource cannot be created.