Container Runtime and Partitioning

What is the EJB Container and which is the EJB Server?

There is some confusion all around on terminology and opinions vary. But the easiest way we found to clarify this is to think about the EJB Server as a logical collection of "services" required by EJBs (e.g. Naming Service, Transaction Service, etc). Physically the services need not be collocated in the same address space although that is possible. The Container is a specialized service in which beans get deployed and their lifecycle, transactions, security, naming, persistence etc are managed according to a specific contract and constrained model that is the EJB spec. To do this the Container uses the generic services provided by the Server. An EJB server is an environment for running EJBeans, including at least one naming service, at least one transaction coordinator, possibly a few databases, and at least one container. A typical server configuration will have exactly one of each of these services.

In IAS, when you say
prompt% vbj com.inprise.ejb.Container ejbcontainer beans.jar -jns -jts –jss -jdb
it is a simplified view of the above where what you launch is a Container that itself starts up in-process the generic services.

You can logically think of this as a Server with 4 generic services (in same address space) with a 5th "special" service - EJB Container - that hosts your beans in beans.jar.

In contrast when you do
% vbj com.inprise.ejb.Container NS -jns
% vbj com.inprise.ejb.Container TS -jts
% vbj com.inprise.ejb.Container DB -jdb
% vbj com.inprise.ejb.Container ejbcontainer beans.jar
% vbj com.inprise.ejb.Container ejbcontainer beans.jar

You now have exactly same application with a vastly distributed execution structure. Now your "EJB Server" is a logical collection of generic services and a replicated Container (for fault tolerance and load balancing)

Why the heck are there two ways of doing most things e.g. starting the Container using vbj launcher and starting using the ias server/console?

Although it might seem that things are easier if there is only one way to do them, it so happens that there are colliding requirements in the user community. For example, there are two operation modes that several of our customers have asked for. One is a "developer friendly" mode and the other is "production mode". Further there is a spilt between users' perception about what constitutes ease of use? To some complete transparency is ease and to others point-click is ease. Some people like their configuration settings to be persisted in central property files (or a Windows registry type thing) while others want to have their preferences be explicit. Also, often you want the convenience of a GUI but at other times desire a way to script things which require commandline utilities.

There is no easy way to satisfy all these camps. So we designed our Container and services to be flexible. You can start an EJB Container like you start any Java program or you can trigger it from a Console where the backend Server kicks the Container up. You can trivially turn on a few flags like -jns -jts to make the Container VM also host the services required by your EJBs or you can have the services run under the auspices of IAS Server with greater control on their lifecycle and properties. Basically we allow users to do what suits their needs at various points in application deveopment.

Is there is any functional difference between the services started using –jns –jts etc (or ejb.jns and ejb.jts properties) versus starting equivalent services using the AppServer daemon?

-jts starts a Container resident lightweight one-phase capable JTS service. Turning on the Transaction Service in the AppServer daemon starts a full two-phase transaction manager.

-jns starts a CosNaming service in the Container process that does not persist its data and uses all default configuration parameters of the VBJ4 Naming Service. Using the AppServer counterpart you can configure it more flexibly but functionally it is equivalent in the sense that they are both exactly the same service.

-jss is the Container’s state repository for stateful session beans. There is no conterpart of this under AppServer.

-jdb starts an inprocess RDBMS. The jdatastore service in the AppServer daemon is functionally equivalent.

Bottomline: The Container builtin services are developer friendly incarnations of services that are functionally complete and equivalent. The difference is in configuration and lifecycle control.

How should I setup the services for best performance?

The performance implications of running each of the services either in process or out of process will depend on the use of that service.

Running the naming service in or out of process will have a negligible performance hit on applications which make little use of naming. Thus, a typical bean which only has its home registered in JNDI at startup will see little difference. However, if that same bean needs to lookup a JNDI name as part of its business logic, then the performance hit will be substantial. (Of course, you should be running only a single naming service per deployment, otherwise each instance of the naming service will contain only a portion of the named objects. Thus, if you run multiple containers, only one will be able to have the naming service in process.)

In general, it is best to always run the JTS in process, as this is heavily used. JNS can generally be run out of process with little impact. JDB should run in process, assuming you make much use of entities (and you are storing then in JDataStore, otherwise there is no need for the -jdb flag in the first place). Finally, JSS could be run out of process, if EJBPassivationTimeout is fairly large, so the container is not continuously doing RPCs to passivate/activate stateful session beans. However, it is likely that you would best run it in process.

Are multiple Containers allowed in a single EJB Server?

You can easily run multiple containers: just run each one in a separate VM. Or, you can put multiple EJBeans into a deployment Jar file, and have multiple EJBeans running in a single Container. Or the beans may be spread across several distinct ejb-jars and a single Container can load all of them. We do not expose the ability to run multiple containers in a single VM, because this flexibility does not add anything: if you want to run multiple EJBeans in a single VM, you can just put them into a single Jar file.

So, the EJB server allows multiple containers (each in a separate VM), and each container allows multiple EJBeans (all in a single or separate Jar files).

What is the relationship between the Container name and jndi name of beans in that Container?

There is no relationship. The server name, "test" or “ejbcontainer”, shouldn't have anything to do with clients from a users viewpoint. Clients locate a bean by using the bean's JNDI name. They need not know anything about "test". The Container name *is* used by the admin utilities to determine which server to stop.

What is the best way to partition beans into Containers for optimal performance?

Each container is a complete, multi-threaded, comprehensive environment for running any number of EJBs. Typically, if you have a large number of JARs (each comprising any number of EJBs) you will run a number of these on each container. For better throughput, you might even run replicas on many containers, if there are EJBs which are frequently used.

Probably, you want to run only one or two containers per box. If the box is a multi-processor, you might run as many containers as you have CPUs and that should give good performance.

Absolutely, you will want cooperating beans collocated in the same container. Typically, these would even be in the same Jar. You also would want to collocate the beans which access the same database, to minimize the number of DB connections, which are a scarce resource.

In summary, look to have about a 1:1 ratio between CPUs and containers. At most, a 2:1 ratio. This will probably mean collocating many Jars into the same containers.

Can I embed a Container into my own “Server”?

You are free to swap out any of the generic services and replace with a different implementation as long as the API contract is adhered to e.g. you can use another vendor’s JNDI Naming Service backend, persist entities to Oracle using an appropriate JDBC driver instead of to JDB (JdataStore) and plugin your custom session storage mechanism instead of using the default JdataStore based storage.

How can I debug the beans I wrote?

With JBuilder (and other environments), it's easy to debug your EJB beans. Create a new project and add a class like the following:
package myPackage;

public class EJBContainerDebugger {

    public static void main(String[] args) {
        try {
            String[] newArgs = {"ejbcontainer", "beans.jar", "-jts", "-jns"};
            System.getProperties().put(“EJBNoClassLoader”); 
              // apparently JB doesn’t work well with breakpoints 
              // if custom classloading is used
            com.inprise.ejb.Container.main(newArgs);
        } catch (Exception x) {
            x.printStackTrace();
        }
    }
}
Set any breakpoints in any beans that you have, and run this project in Debug mode. Be sure to set up any - D parameters in the Project Parameters section. You can also place any command line arguments there as well, in lieu of the way hardcoded above. The server should be running in debug mode. Now run the client from another project. When the client invokes a call to a bean where you have set a breakpoint, execution will stop and you can debug like normal.

Are there any startup services or hooks that I can use to initially create some service classes within the EJB container? I.e., can I get a piece of my code run automatically at container startup?

The simplest way to do this is to start your own "shell" main program, and launch the container from within it. For example:
public class Shell {

  public static void main(String[] args) throws Exception {
    // do your startup stuff here...
    com.inprise.ejb.Container.main(args);
  }

}
This will allow you to startup services within the shell.

Is there some way in which initialization code can be executed when the container starts up - but *before* it starts serving clients.

The motivation for wanting to do something like this is to call some initialization session bean 'manually' or initializing a framework, etc. which needs to happen before clients start hitting the server. Unfortunately there is no simple way to insert a framework into the Container between the time that the EJBs are initialized, and the time that the first client request comes in. Basically, as soon as the JNDI name is registered, the beans are "public".

You can insert code before the EJBs are initialized, and you can insert code after afterward, but you cannot guarantee that the insertion happens before a client request comes in.

In summary, here are the points where you can insert your code:

main() {
  // insert code here
  "start the container and any services, but no beans"
  // insert code here
  "add a Jar file of EJBs"
  // insert code here
  "add another Jar file of EJBs"
  // etc.
}

Can I start a Container from my “main” program?

Look above.

How can I collocate EJBs with CORBA objects?

The work required, if you are willing to use the standalone EJB container is fairly minimal:

  1. Write a main program.

  2. Run the container (new Container().run(args)) from within the main program, setting a system property EJBNoSleep, causing the EJB container to not block the current thread.

  3. Obtain the EJB container's ORB via the following call:
            orb = (org.omg.CORBA.ORB) context.lookup("java:comp/ORB");
    

  4. Instantiate your CORBA servers, putting them into JNDI (or use CosNaming, if you prefer).

  5. Access the CORBA objects from within your EJBs using JNDI.