Class Loader and Java /J2EE Application Packaging

Just a step forward to discuss about java and j2EE class loader and Java/J2EE application packaging. Mainly on the complex J2EE application packaging.

Tuesday, December 19, 2006

Packaging J2EE Application

Most of the IDEs provide tools or wizards for packaging J2EE application. Packaging a J2EE application application using these tools or wizards are straightforward and simple as the tool takes care of the packaging. Most of the time the developers don't bother to look at the underlying scripts (like ant script) which takes care of the packaging. When it comes to package the application for optimization or to maintain proper dependency between application modules without redundancy copy of modules then it becomes necessary to play around the underlying scripts of the IDE or tools that takes care of the packaging or it may be required to do the packaging by writing your own scripts.( For example ant script or shell scripts) The different scenarios of J2EE application may need different approaches for packaging. For example
  1. Application with stand alone web modules without any interdependency. No sharing of libraries between web modules(also EJB modules). Each module has it's own library copy.
  2. Application with more than one modules(multiple web and multiple EJB modules) and the application want to share the same library JAR file among all the modules rather than bundle duplicate copies of library in each module.
  3. Multiple applications need to share the same library JAR file among the applications not just among modules.
  4. The J2EE application may expect a library to be made available by the server and want to use that library instead of having it's own library included on the ear file(For example a Logging library).

The below given approaches addresses addresses some of the common scenarios that a J2EE developer may face during an application development and a recommended packaging structure for the same.

Approach 1 : No sharing of Libraries between modules

This is the most simplest approach for packaging a J2EE application. In this case the developers may not need to touch the underlying scripts of IDE tools. In this case one module has all the libraries that it needs. That is to package all the required jar files for the EJB jar file under the root of the jar file and in case of web application add all the utility and library classes under the WEB-INF\lib folder.

Let us take the following example: Let the J2EE application has following modules.

  1. One EJB Module (Let it be ejb1.jar )
  2. One EJB Client Module (Let it be ejb1_client.jar )
  3. Two Web Module which depends on the ejb client classes( Let it be web1.war)
  4. One Utility jar file containing all the utility classes (Let it be util.jar)

If the above modules are packaged in the above approach to create a J2EE ear file let it be app1.ear, then the app1.ear structure will look like the below given diagram.(To keep the diagram simple only the files that affects the packaging method are shown )

    app1.ear
        META_INF/application.xml
        ejb.jar
            META-INF/ejb-jar.xml
            ejb1_client.jar
            util.jar
        web1.war
            WEB-INF/web.xml
            WEB-INF/lib/ejb1_client.jar
            WEB-INF/lib/util.jar
        web2.war
            WEB-INF/web.xml
            WEB-INF/lib/ejb1_client.jar
            WEB-INF/lib/util.jar

The files shown in blue color are duplicated on each module to make sure the module has all the necessary library that it needs.

Approach 2 : Multiple modules in the same application sharing the library

This approach is better than the above approach in some scenarios as this removes the duplicate copy of library files while still maintaining the portability of the application. In this approach all the libraries are withing the .ear file, but instead of having duplicated copy of library files the modules keep a reference to the single shared library that is within the .ear file. Details are described below.

As per the J2EE 1.4 specification a JAR format file (such as a .jar file, .war file, or .rar file) can reference a .jar file by naming the referenced .jar file in the Class-Path header entry of the referencing JAR file’s manifest file. The referenced .jar file is referred using a URL relative to the URL of the referencing JAR file. The Manifest file is named META-INF/MANIFEST.MF in the JAR file. The Class-Path entry in the Manifest file is of the form

Class-Path: list-of-jar-files-separated-by-spaces

Now let us consider the above example and package the application using the jar file reference concept as specified in J2EE 1.4 specification.

The application ear file structure will look like the below given diagram.

    app2.ear
        META_INF/application.xml
        ejb1_client.jar
        utl.jar
        ejb.jar       Class-Path: ejb1_client.jat util.jar
             META-INF/ejb-jar.xml
        web1.war   Class-Path: ejb1_client.jat util.jar
            WEB-INF/web.xml
        web2.war   Class-Path: ejb1_client.jat util.jar
            WEB-INF/web.xml

As given in above the EAR file structure, the common libraries or packages are kept on the root of the application ear file and references to these files are given in each modules ( jar / war files). The Class-path entry of each META-INF/MANIFEST.MF file is shown in green color.

Approach 3 : Multiple applications sharing the same library.

In some cases different applications on the same application server uses the same library. For example the logging mechanism or the JDBC driver .If an organization uses oracle database through out the enterprise then all the application developer can expect the oracle driver to be made available to the application by the application server, instead of each application having a duplicate copy of the JDBC library. This approach may also help in replacing the common library for all application without replacing one by one for each application. Such libraries are often called installed libraries. As per J2EE 1.4 specification this can be done by adding the reference to the external libraries by the 'Extension-List' attribute in the manifest file to reference one or more library JAR files that are not bundled in the EAR file but are installed in some well-known location, usually the lib/ext directory of the Java Runtime Environment (JRE). In this approach, the library JAR files are not included as part of the EAR file but the extension list include their reference. Any library JAR file referenced is external to the EAR file must be installed in the lib/ext directory, and should be made available by the application server.

In the application EAR file, the Extension-List attribute of the manifest file is used to express the dependency of the EAR file on a library JAR file. More than one library can be listed in the Extension-List. The applications will not deploy if the application server cannot find the library and resolve the dependency.

Let us take the above example repackage the application expecting the util.jar library to be present as a installed library in the target application server. In this case the package will look like the below given diagram.

    app3.ear
        META_INF/application.xml
        ejb1_client.jar
 ejb.jar  
     META-INF/MANIFEST.MF
                Class-Path: ejb1_client.jar
                Extension-List.util
                Util-Extension-Name: com/example/util
                Util-Extension-Specification-Version: 1.0
        web1.war :
            META-INF/MANIFEST.MF
                Class-Path: ejb1_client.jar
                Extension-List.util
                Util-Extension-Name: com/example/util
                Util-Extension-Specification-Version: 1.0
            WEB-INF/web.xml
        web2.war
            META-INF/MANIFEST.MF
                Class-Path: ejb1_client.jar
                Extension-List.util
                Util-Extension-Name: com/example/util
                Util-Extension-Specification-Version: 1.0
            WEB-INF/web.xml

For an .ear file to work with external optional package reference the referred jar library should have proper header information in the MANIFEST.MF file. For the above example the util.jar file should have following information in the MANIFEST.MF file to make sure the ear file gets loaded properly.

Extension-Name: com/example/util
Specification-Title: example.com’s util package
Specification-Version: 1.0
Specification-Vendor: example.com

J2EE specification gives the what is expected from an application server and leaves the implementation details to the vendors. Different vendors implemens the specification in their own ways and also gives some additional vendor specific features for tunning the application. Some of them will be discusses in comming blogs.

Thursday, December 14, 2006

Class Loading in J2EE

Although the J2EE specification does not define a fixed classloader structure but some of the specifications impacts the class loading process significantly. The specifications that affects the class loading process are
  • Applications are component-based, co-resident but separate, and reloadable.
  • Ability of Servlets and JSPs to call EJBs, and for all three to be able to use resource adapters.
  • Web-modules within an application are required to be isolated from one another.
  • With EJB 2.x local interfaces add the requirement that implementation classes should also be visible.
J2EE application servers must arrange the classloaders hierarchy to make sure that each module has the correct visibility to meet the above J2EE specifications. Below diagram shows a typical classloader hierarchy structure for a typical J2EE Application server for loading an EAR file containing multiple web modules, EJBs and resource-adapters.

The above diagram shows a typical classloader hierarchy of J2EE application server, but there is no guarantee that the same hierarchy will be available in all application server. The alternate hierarchy may be as given below in the diagram.

Thursday, November 09, 2006

Understanding Class Loading Basics From Packaging Point of View

The Java / J2EE application packaging basics lies in understanding the class loading architecture of J2EE application servers or servlet containers. Understanding the details of J2EE class loading architecture will help in understanding and analyzing different approaches of packaging J2EE application.
Class loading is the process of locating the bytes for a given class and converting them into a Java Class instance. All java virtual machine's has a built-in class loader object, called the "bootstrap class loader" that starts the process of class loading.
A Class Loader object is an instance of a child class of the abstract class java.lang.ClassLoader. The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader except the root ClassLoader object. When a program or application requests to find a class or resource, a ClassLoader instance delegates the search for the class or resource to its parent class loader before attempting to find the class or resource itself. If the class loader at the top of the hierarchy cannot fulfill the request, then the child class tries to load the class. If the child is also unable to load the class, the request continues back down the hierarchy until a class loader fulfills it or the ClassLoader at the bottom of the hierarchy throws ClassNotFoundException.
Note : Some of the application server provides option to change this delegation mode from parent first to parent last mode.
Each ClassLoader defines it's own unique and separate namespace. The classes that are included in this name space are the classes that are loaded by the ClassLoader instance itself and the classes that are loaded by it's parent ClassLoaders in the hierarchy. A ClassLoader can have only one instance of a given Class in it's namespace. But the same class can be loaded into the namespace of another ClassLoader.
Let's take an example.

In the above diagram ClassLoaderB's name space included the classed loaded by Bootstrap ClassLoader, Classloaded by ClassLoaderA and the classes loaded by itself. If the ClassLoaderB loads the class 'MyClass' then the same can also be loaded again by ClassLoaderC. But a class 'OtherClass' is loaded by ClassLoaderA then the same Class is visible to both ClassLoaderB and ClassLoadereC's namespace and they will not load the class 'OtherClass' again to it's namespace.

Background

While developing a java application specially a J2EE application, generally more importance is given to the code, the framework used and it's optimization and most of the time the packaging gets overlooked.
Generally developers package the J2EE applications using some tools or wizard. It works well for simple web projects or J2EE application, which has few web applications. But when it comes to complex J2EE application with many interdependency this approach some time may work, but might not optimized. This blog is mainly to discuss the class loader details starting from the basics to vendor specific way of packaging application.