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. For more information about
registering services, see Registering OSGi services.
- 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"/>