I'm currently working on a OC4J migration project. One requirement is that a specific EJB module is instantiated before all other EJB modules.
Most surprisingly, in OC4J the instantiation order of the EJB modules is arbitrary. To get around this, you can use a technique that works with a simple main class. When I came around this, I called it "poor man's startup classes", but it is more flexible than startup classes and could be deployed in a standard J2EE EAR file.
How does it work?
The J2EE spec includes a module type called application client. An application client is usually a programme which calls the J2EE application and makes some actions with it.
Application clients are deployed with the whole J2EE application and are co-located. This means that you have access to the JNDI context without specifying any connection details.
An application client is a normal Java application packaged in a normal JAR file and through the Main-Class tag in the META-INF/Manifest.mf. In the META-INF you must also include the client-application.xml file for the usual <ejb-ref> and other J2EE references. This complete application can be tested like a normal standalone J2EE client application without deploying it to OC4J.
So far so good. Now, we include this JAR file in the EAR file. The application.xml needs a new module entry like this:
<module>
<java>appclient.jar</java>
</module>
To get this application started we need the OC4J-specific deployment descriptor orion-application.xml in the META-INF directory of the EAR file. This file needs an entry to start the application client automatically:
<client-module auto-start="true" path="appclient.jar" user="admin" />
Package everything in a single J2EE EAR and deploy it to your OC4J instance. Restart the OC4J instance and everything works as desired.
Where is the ordering?
The application client handles the ordering. This is done programmatically and could be used in a J2EE container independent fashion (if they support automatic start of application clients).