Please forgive my pitiful knowledge of Java EJBs but, when an EJB is deployed to an application server as a .jar file, where do things like Hibernate and log4j first look for their configuration files (hibernate.cfg.xml and log4j.properties) in the .jar file?
I think Log4j would look in more than one place for log4j.properties file. Anyway, all configuration files in an ejb-jar go inside the META-INF directory.
(...) when an EJB is deployed to an application server as a .jar file, where do things like Hibernate and log4j first look for their configuration files (hibernate.cfg.xml and log4j.properties) in the .jar file?
This depends on the implementation of the tool and is unrelated to the fact that you are using EJBs. For Hibernate, the documentation writes:
3.7. XML configuration file
An alternative approach to configuration is to specify a full configuration in a file named
hibernate.cfg.xml
. This file can be used as a replacement for thehibernate.properties
file or, if both are present, to override properties.The XML configuration file is by default expected to be in the root of your
CLASSPATH
.
Regarding Log4J, the procedure is described below:
Default Initialization Procedure
The log4j library does not make any assumptions about its environment. In particular, there are no default log4j appenders. Under certain well-defined circumstances however, the static inializer of the
Logger
class will attempt to automatically configure log4j. The Java language guarantees that the static initializer of a class is called once and only once during the loading of a class into memory. It is important to remember that different classloaders may load distinct copies of the same class. These copies of the same class are considered as totally unrelated by the JVM.The default initialization is very useful in environments where the exact entry point to the application depends on the runtime environment. For example, the same application can be used as a stand-alone application, as an applet, or as a servlet under the control of a web-server.
The exact default initialization algorithm is defined as follows:
- Setting the
log4j.defaultInitOverride
system property to any other value then "false" will cause log4j to skip the default initialization procedure (this procedure).- Set the
resource
string variable to the value of thelog4j.configuration
system property. The preferred way to specify the default initialization file is through thelog4j.configuration
system property. In case the system propertylog4j.configuration
is not defined, then set the string variable resource to its default value "log4j.properties".- Attempt to convert the
resource
variable to a URL.- If the resource variable cannot be converted to a URL, for example due to a
MalformedURLException
, then search for the resource from the classpath by callingorg.apache.log4j.helpers.Loader.getResource(resource, Logger.class)
which returns a URL. Note that the string "log4j.properties" constitutes a malformed URL. SeeLoader.getResource(java.lang.String)
for the list of searched locations.- If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL. The
PropertyConfigurator
will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in which case theDOMConfigurator
will be used. You can optionaly specify a custom configurator. The value of thelog4j.configuratorClass
system property is taken as the fully qualified class name of your custom configurator. The custom configurator you specify must implement theConfigurator
interface.
To summarize, if you put both files at the root of your EJB-JAR, they should be found.
Regarding the title of your question, I suggest to read Packaging EJB 3 Applications that I'm quoting below:
Dependencies between Java EE modules
Unfortunately, no Java EE specification provides a standard for class loading, and each application server implements class loaders in whatever way seems best to the vendor. However, Java EE defines the visibility and sharing of classes between different modules, and we can depict the dependency between different modules as shown in figure 4.
As illustrated in figure 4, the EAR class loader loads all JARs in the lib directory that is shared between multiple modules. Typically a single EJB class loader loads all EJB packaged in all EJB-JAR modules. The EJB class loader is often the child of the application class loader, and loads all EJB classes. Because the EJB is a child to the EAR class loader, all classes loaded at the> EAR level will be visible to the EJBs.
Figure 4: Illustration of class visibility of an EAR file containing multiple web modules, EJBs, and shared library modules. The EAR class loader loads the classes in the JARs packaged as library modules, and all classes loaded by the EAR class loader are visible to the EJBs. The classes loaded by EJB class loader are typically visible to the web module in most containers because the WAR class loader is a child of the EJB class loader.