- Naming Server/Naming Provider
This is the actual repository of names to object mapping. IAS ships with a complete implementation of OMG CosNaming which provides a naming service for CORBA objects.
- JNDI API
A client side API defined by Sun that allows Java clients to access any naming service (CosNaming, LDAP,
etc). This makes the client code portable and independent of the particular naming provider.
- JNDI SPI
An API whose implementations are targeted to a specific Naming provider. It plugs into the JNDI API to map the access to the specific Naming provider.
- Naming Service bootstrap
The Naming service allows one to locate objects. That still leaves open the issue of how to locate the
Naming Service in the first place. All Naming Providers have their own bootstrap protocols. JNDI abstracts
these mechanisms into a uniform initialization system that is customizable using properties.
javax.naming.Context ctx = new javax.naming.InitialContext();
everywhere - within beans, within java clients, from servlets, whatever. Things will magically default to using the correct JNDI properties.
We are using the JNDI 1.2 properties mechanism which lets all the configuration parameters be defined in a jndi.properties file. Its easiest to have this file on the CLASSPATH and hence we have put it in vbejb.jar. This way all flavours of code - ejbs, servlets and java clients have the same mechanism for getting the InitialContext. The user is free to override properties by passing in a property table as an argument to the C'tor or by setting System properties or providing a jndi.properties file earlier in CLASSPATH - this is straight from the specification of JNDI 1.2 - no proprietary mechanisms.
java.naming.factory.initial must be set. Further, to
support the “java:comp” namespace we require the java.naming.factory.url.pkgs property be also set.
You need to set these properties to the following values:
java.naming.factory.initial = com.inprise.j2ee.jndi.CtxFactory java.naming.factory.url.pkgs = com.inprise.j2eeThere are several mechanisms for setting these properties – via a System property, property file and using arguments to the call.
When you are in the role of a Bean Developer, you can easily construct a valid initial context in any bean by simply invoking the no-arg constructor since the EJB server has already set the required properties (as per the EJB 1.1 spec.)
However, for a client (or more correctly, “non-contained” code), this property must be set explicitly. You have two choices:
1) You can specify the value of java.naming.factory.* as a System property, and use the no- arg constructor (e.g., new javax.naming.InitialContext()). To do this, run as follows:
% vbj -Djava.naming.factory.initial=com.inprise.j2ee.jndi.CtxFactory \
–Djava.naming.factory.url.pkgs=com.inprise.j2ee MyClient
2) You can not specify the value of java.naming.factory.* as a System property, and instead specify it as a value in a local hash-table passed into the non default constructor (e.g., new javax.naming.InitialContext(env).
javax.naming.Context context;
{
// get a JNDI context using the Naming service
Hashtable env = new Hashtable();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
"com.inprise.j2ee.jndi.CtxFactory");
env.put(javax.naming.Context.URL_PKG_PREFIXES,
"com.inprise.j2ee");
context = new javax.naming.InitialContext(env);
}
Note that the value of the above constant
javax.naming.Context.INITIAL_CONTEXT_FACTORY
is:
"java.naming.factory.initial"
3) Call the no-arg constructor in code and use a jndi.properties property file (as defined in the JNDI 1.2 specification) to set the relevant properties. (This is what our product does)
1) To locate the naming service. This is done once per client. This is a classic bootstrap problem. Either you hard code the bootstrap location, or you use a discovery protocol. Over the years our customers have repeatedly preferred dynamic discovery over static hard-coding.
2) In fail-over scenarios. These scenarios are outlined in another section.
prompt>vbj com.inprise.ejb.Container ejbcontainer sort_beans.jar -jts -jns
Inprise EJB Container
=====================
[snip]
Initializing ORB..... done
Initializing
JNS..................................................................................... done
Initializing JTS................................... done
** Not using security **
EJB Container Statistics
========================
Time Mon Oct 11 15:15:59 GMT+13:00 1999
Memory (used) 1363 Kb (max 1363 Kb)
Memory (total) 2047 Kb (max 2047 Kb)
Memory (free) 33.0%
------------------------
Home sort
Total in memory 0
Total in use 0
========================
Container [ejbcontainer] is ready
Things to notice: The JNS initialization takes a looooonnnng time, but is still 'done', and the Container does
end up in a 'ready' state, eventually.
When the SortClient attempts to connect to the container, we get the following stack-trace:
C:\Inprise\AppServer\examples\ejb\sort>vbj SortClient
Exception in thread "main" org.omg.CORBA.OBJECT_NOT_EXIST:
Could not locate the following object:
repository id :
IDL:inprise.com/CosNamingExt/ExtendedNamingContextFactory:1.0
How did the Naming Service start and does it make sense to start an EJB that nobody can find?
First of all, it is not a failure if the naming service is not registered with the OSAgent. It is perfectly reasonable for one to create an instance of the Naming Service and not register it with the agent. For example, if I use Iona's product, and instantiate a naming service, it will not be registered with the OSAgent. This is perfectly legitimate.
However, it is not very useful for clients that depend on the osagent for bootstrapping their Naming Service.
To solve this problem, the OMG has introduced INS (stands for "Interoperable Naming Service") which provides a mechanism for any IIOP client to locate a naming service. Our naming service provides an implementation of INS and hence it allows non-osagent bootstrap.
So, again, the container is not doing anything wrong. It is creating CORBA services, which are ready for the client to use.
1.It doesn't scale - to large numbers of clients (queries per second), entries (servers or
objects), or subnets.
This goes away since in the AppServer the osagent is used as the high-availability solution for
clusters of EJB servers rather than a naming mechanism. The Naming Service itself has been redesigned to scale and be fault tolerant.
2.It forces the use of proprietary APIs
This mostly goes way with EJB because it is the container that uses the proprietary
APIs, not customer code.
3. Persistence of naming data
Again by not using the osagent as a naming service this issue goes away since the VBJ4 Naming Service has very good support for backing stores.
java.naming.factory.initial,
and
java.naming.provider.url
Command line example:
C:\ejb\examples\sort>java
-Djava.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
-Djava.naming.provider.url=ldap://rogue.inprise.com:389/
com.inprise.ejb.Container ejbcontainer mybeans.jar
Clients need to be similarly configured.
Of course you can set these as JNDI properties in the jndi.properties file.
Consider what happens when you start a container, specifying the "-jns" flag:
1) An instance of the naming service is started
2) The container's objects are put into the naming service.
Now, consider what happens when you start two containers, with different beans:
1) An instance of the naming service is started (NS.A)
2) The container's objects (EJB.A) are put into the naming service (NS.A)
3) An instance of the naming service is started (NS.B)
4) The container's objects (EJB.B) are put into the naming service (NS.B)
Note: we register all beans deployed in a Container in its own Naming Service (–jns) in preference to any other Name Servers that may be available in the domain.
Then your client starts up and looks for objects. There are two instances of the naming service available. Using the OSAgent, the client round-robins between the two naming services. Unfortunately, each naming service only references half of the objects. Thus, you client will fail half the time!
There are a number of solutions:
One solution is to start only one instance of the naming service.
This can be done by specifying "-jns" to at most one of the containers. Or, you can simply start
a special container which is only the naming service, via:
prompt% vbj com.inprise.ejb.Container foobar -jns
Then you would not specify "-jns" to any of the other containers, and they will all populate this
first naming service.
Another solution is to put all your beans into both containers. Then the round robin behavior will actually provide load balancing, as half of your clients will access container A, and half will access container B. As long as they both have all the beans, you will get twice the throughput. (Actually, not quite twice, since typically the database is not replicated, and thus is still a bottleneck.)
The bottom line is that we need to be able to shut down one IAS server and have applications that were using it automatically fail over to the other one.
One option is to put the Naming data into a database backing store and have AppCenter monitor the naming service.
Alternatively, what you want to do is to use the master-slave configuration for the naming service. Using this configuration, none of your IAS instances will actually start the NS. You will start this explicitly, using the "namserv" executable. (Please refer to the NS docs for information on configuring the master-slave.) Then, your various IAS instances will always store their names with this shared NS. If the master NS fails, the slave NS will continue servicing clients.
You can register the same sets of beans in each container to get a homogeneous clustering capability, or you can partition your beans across various containers to get a heterogeneous clustering capability.
You should then be able to kill of IAS instances, and your clients will fail over to the IAS replicas. Your stateless SBs and entity beans would fail over immediately. You can configure your stateful SBs to fail over, by sharing a Stateful Session Storage Service among them. To do this, run a single instance of the container with only the -jss flag, and don't specify the -jss flag to all the other containers. This will centralize stateful session state in that single jss instance. This should allow fail over of stateful SBs, as well.