You can make an object available in the default Java™ Naming and Directory Interface (JNDI) namespace. To do that, you must register it in the
OSGi service registry with the osgi.jndi.service.name
service property. The value
of osgi.jndi.service.name
is the required JNDI name. Similarly, to find an object
in the default JNDI namespace, you can search the OSGi service registry with the
osgi.jndi.service.name
service property. The value of
osgi.jndi.service.name
is the JNDI name.
About this task
Compared with explicitly calling Context.bind
or
Context.lookup
, using the service registry has the following benefits:
- Your feature works properly when
jndi-1.0
is enabled, but your feature does not
need an explicit dependency on JNDI.
- You do not need to explicitly unbind objects from JNDI when your feature is removed because the
OSGi framework automatically unregisters services when bundles are stopped.
- You can easily implement lazy initialization using declarative services or
ServiceFactory
rather than using Reference
and
ObjectFactory
.
For more information about JNDI, see Naming.
Procedure
- Register a service using the
osgi.jndi.service.name
property with the
JNDI name.
- Update your metatype.xml to allow a JNDI name to be
specified in server configuration.
To allow users to specify a JNDI name for your service, use the
jndiName
id
for consistency with other features in the
Liberty run time, for
example:
<AD id="jndiName" name="JNDI name" description="JNDI name for a widget." type="String" ibm:unique="jndiName"/>
You
can use an internal attribute to automatically set the
osgi.jndi.service.name
service property with the value of the
jndiName
attribute, for
example:
<AD id="osgi.jndi.service.name" name="internal" description="internal" type="String" default="${jndiName}"/>
For
more information about OSGi Metatype, see
Advanced Configuration.
- Implement the
ResourceFactory
interface if you need Java EE resource
reference information. If your service needs Java EE resource reference information, such
as res-auth
, you can register a ResourceFactory
in the OSGi
service registry with the jndiName
and creates.objectClass
properties. The ResourceFactory
service is re-registered automatically with the
osgi.jndi.service.name
property.
For
example:
import com.ibm.wsspi.resource.ResourceFactory;
public class WidgetResourceFactory implements ResourceFactory { ... }
Properties properties = new Properties();
properties.put(ResourceFactory.JNDI_NAME, "widget/abc");
properties.put(ResourceFactory.CREATES_OBJECT_CLASS, Widget.class.getName());
bundleContext.registerService(ResourceFactory.class, new WidgetResourceFactory(), properties);
Alternatively,
the service could be registered automatically using declarative services and metatype. In that case,
you can specify the
creates.objectClass
property as a declarative services
property. You do not need to specify the
jndiName
property because it is set
automatically from the user configuration with the
<AD id="jndiName">
element in
the
metatype.xml file in step
2, and you do not
need an
<AD id="osgi.jndi.service.name>
element in the
metatype.xml file because the
ResourceFactory
service will be
re-registered automatically.
- Locate an object using the
osgi.jndi.service.name
property with the JNDI
name. For example:
bundleContext.getServiceReference(DataSource.class, "(osgi.jndi.service.name=jdbc/myds)");
Alternatively,
you can locate a ResourceFactory
using the jndiName
and
creates.objectClass
properties.
- Update your metatype.xml to allow a resource to be specified in
server.xml using the id of the resource. This allows the resource to be
accessed regardless of whether or not the resource has a
jndiName
.
For example,
<AD id="dataSourceRef" type="String" ibm:type="pid" ibm:reference="com.ibm.ws.jdbc.dataSource"
cardinality="1" name="%dataSourceRef" description="%dataSourceRef.desc"/>
If
you are using declarative services, you can use an internal attribute to set a
.target
service property with a filter. For example, if your declarative services
component has a reference named
dataSource
, you can use the following attribute
definition to ensure that the dataSource that is referenced by the dataSourceRef configuration
attribute is
used.
<AD id="dataSource.target" type="String" default="(service.pid=${dataSourceRef})" ibm:final="true" name="internal" description="internal"/>