| The Essential Components

## Building in Extensibility

> If you followed the steps described in this lesson so far, then you should have a complete, functional context implementation. However, such a context implementation would be closed in the sense that the types of objects that can be read and stored by using the context implementation would be limited to what the context implementation was coded to accept. The JNDI provides utilities for making context implementations extensible. These utilities allow objects that are passed by the program to be transformed before they reach the context implementation, and allow objects that are read from the directory to be transformed before they reach the program.

> #### Reading Objects

> The Object Factories lesson describes how a service provider should use `NamingManager.getObjectInstance()` or `DirectoryManager.getObjectInstance()` before returning an object to the user program from one of the following methods:
> - `Context.lookup(Name name)`
> - `Context.lookupLink(Name name)`
> - `Binding.getObject()`
> - `SearchResult.getObject()`
> Following is how the hierarchical namespace example calls `getObjectInstance()` in its `lookup()` method. It uses the method in the `NamingManager` class because `HierCtx` implements only the `Context` interface. If a context implementation implements the `DirContext` interface, then it should use the one in the `DirectoryManager` class. See the Adding Directory Support lesson for details.

> >     // Code that determined "inter" is the object bound to the
> >     // atomic name "atom"
> >         ...

> >     // Call getObjectInstance for using any object factories
> >     try {
> >         return NamingManager.getObjectInstance(inter,
> >             new CompositeName().add(atom), this, myEnv);
> >     } catch (Exception e) {
> >         NamingException ne = new NamingException("getObjectInstance failed");
> >         ne.setRootCause(e);
> >         throw ne;
> >     }

> You should pass to `getObjectInstance()` the name of the object as a composite name and the context in which the name should be resolved. This need not be the deepest context (that is, the name need not be atomic). You should also pass in the context's environment properties in case the object factories need them.

> Similarly, when returning the enumeration generated by `Context.listBindings()` , you should call `getObjectInstance()` for the object in each `Binding` in the enumeration. Here is the definition of the enumeration's `next()` method.

> >     public Object next() throws NamingException {
> >         String name = (String)names.nextElement();
> >         Object obj = bindings.get(name);

> >         try {
> >     	obj = NamingManager.getObjectInstance(obj,
> >     	    new CompositeName().add(name), HierCtx.this,
> >     	    HierCtx.this.myEnv);
> >         } catch (Exception e) {
> >     	NamingException ne = new NamingException("getObjectInstance failed");
> >     	ne.setRootCause(e);
> >     	throw ne;
> >         }

> >         return new Binding(name, obj);
> >     }

> This example shows a static approach, in which `getObjectInstance()` is called as you create each `Binding` instance. Another approach is to define your own `Binding` subclass and override `Binding.getObject()` to call `getObjectInstance()`. (The result of `getObjectInstance()` could be cached to avoid repeated invocations.)

> #### Storing Objects

> The State Factories lesson describes how a service provider should use `NamingManager.getStateToBind()` or `DirectoryManager.getStateToBind()` before storing an object given by the user program to one of the following methods:
> - `Context.bind(Name name, Object obj)`
> - `DirContext.bind(Name name, Object obj, Attributes attrs)`
> - `Context.rebind(Name name, Object obj)`
> - `DirContext.rebind(Name name, Object obj, Attributes attrs)`
> Here is how the hierarchical namespace example calls `getStateToBind()` in its `bind()` and `rebind()` methods. It uses the method in the `NamingManager` class because `HierCtx` implements only the `Context` interface. If a context implementation implements the `DirContext` interface, then it should use the one in the `DirectoryManager` class. See the Adding Directory Support lesson for details.

> >     // Code that determines that this is the context in which
> >     // to bind the atomic name "atom" to the object "obj"
> >         ...

> >     // Call getStateToBind for using any state factories
> >     obj = NamingManager.getStateToBind(obj,
> >         new CompositeName().add(atom), this, myEnv);

> >     // Add the object to the internal data structure
> >     bindings.put(atom, obj);

> You should pass to `getStateToBind()` the name of the object as a composite name and the context in which the name will be resolved. This need not be the deepest context (that is, the name need not be atomic). You should also pass in the context's environment properties in case the state factories need them.

> Note that this implementation is simplistic because the example can store any type of object. A more realistic implementation would check the result of `getStateToBind()` to ensure that the object is of a type that it can store. See the State Factories lesson for details.

| The Essential Components