I'd like my custom OSGi Liberty feature to inject/lookup JNDI datasource, the one that is already defined 'as usual'. Something like this:
<server description="my-server">
<!-- I prefer this, not being forced to define url, driver, username and password here as well -->
<myJdbcRegistry dataSourceJndiName="jdbc/myDataSource" />
<!-- This dataSource exists anyway, i do not want to repeat all attributes that are inside properties.oracle -->
<dataSource id="my-dataSource" connectionManagerRef="connection-manager" jndiName="jdbc/myDataSource" transactional="true" type="javax.sql.DataSource">
<jdbcDriver libraryRef="oracle-ojdbc8-library"/>
<properties.oracle URL="${my.db.url}" driverType="thin" password="{xor}${my.db.password}" user="${my.db.user}"/>
</dataSource>
<library id="oracle-ojdbc8-library">
<fileset dir="${shared.resource.dir}/jdbc" includes="ojdbc8-19.7.0.0.jar"/>
</library>
Is this even possible to do? I tried several approaches without results (different InitialContext lookups, OSGi BundleContext#createFilter, BundleContext#getServiceReferences).
Yes, it's possible, but there is some complexity to it. The dataSource
element isn't actually a DataSource. It's a ResourceFactory for creating a data source based on a resource reference. In Liberty, configuration usually references other configuration by its id
, so more typical configuration that follows conventions of other config elements would look like this:
<myJdbcRegistry dataSourceRef="my-dataSource"/>
Here's an example from Liberty code itself where another configuration element requires a dataSource and references it by id,
<AD id="dataSourceRef" type="String" default="DefaultDataSource" ibm:type="pid" ibm:reference="com.ibm.ws.jdbc.dataSource" name="%dataSource" description="%dataSoure.desc"/>
<AD id="DataSourceFactory.target" type="String" default="(service.pid=${dataSourceRef})" ibm:final="true" name="internal" description="internal use only"/>
@Reference(target = "(id=unbound)")
protected void setDataSourceFactory(ResourceFactory svc) {
ResourceConfig resourceInfo = resourceConfigFactory.createResourceConfig(DataSource.class.getName());
resourceInfo.setSharingScope(ResourceConfig.SHARING_SCOPE_SHAREABLE);
resourceInfo.setIsolationLevel(isolationLevel);
resourceInfo.setResAuthType(ResourceConfig.AUTH_CONTAINER);
...
DataSource dataSource = (DataSource) dataSourceFactory.createResource(resourceInfo);