Isolating sub deployments
Supposing you have an application that is made up of a Web application, an EJB module and a JAR file containing utility classes. All sub deployments are placed at the root of the archive, so that they will be able to see each other. This can be convenient, however, supposing that your Web application contains itself some implementations of the same EJB. That's absolutely possible since Java EE 6 specification allow your Web application to include EJB classes within the WEB-INF/classes or WEB-INF/lib folder.
How does the classloader solves this conflict? The application server classloader has a priority list when loading classes that are used to avoid any conflict between loaded classes.
- The maximum priority is given to modules, automatically, by the container, including the Java EE APIs. Libraries that are contained in the modules folder are included in this category.
- Then libraries that are indicated by the user within the MANIFEST.MF of the packaged archive as Dependencies(or in the jboss-deployment-structure.xml file).
- Next, libraries that are packed within the application itself, such as classes contained in WEB-INF/lib or WEB-INF/classes.
- Finally, libraries that are packed within the same EAR archive (in the EAR's lib folder).
So, in this example, the EJB libraries located in the WEB-INF folder will "hide" the implementations of EJB.jar top-level deployment. Whether or not this is the desired action from the container, you can still override it:
<jboss-deployment-structure> <ear-subdeployments-isolated>false</ear-subdeployments-isolated> <sub-deployment name="WebApp.war"> <dependencies> <module name="deployment.App.ear.EJB.jar" /> </dependencies> </sub-deployment> </jboss-deployment-structure>
In this example, we have added a dependency to the EJB.jar, which is placed at the root of the archive, which will override the implementation packed within the Web application.
Notice the ear-subdeployments-isolated element placed at the top of the file. By setting the EAR isolation level, you will be able to indicate if the sub-deployments modules are visible to each other.
The default value for this attribute is false, meaning that the sub-deployment modules will be able to see each other. If you are setting isolation to true each module will be then picked up by a different classloader, so, in our example, the Web application will not be able to find the classes contained in EJB.jar and Utility.jar library.
If you want to keep deployment isolated, but allow visibility for some of them, then you have several choices available:
- Move the library to the EAR/lib folder, so that it will be picked up as a separate module
- Specify a dependency using Dependencies or using Class-Path in the MANIFEST.MF file of the calling application
From the following screenshot, you can see how you could correctly set up your EAR, by placing common libraries in the lib folder, and adding a dependency to the EJB classes:
And this is the corresponding configuration required in jboss-deployment-structure.xml:
<jboss-deployment-structure> <ear-subdeployments-isolated>true</ear-subdeployments-isolated> <sub-deployment name="WebApp.war"> <dependencies> <module name="deployment.App.ear.EJB.jar" /> </dependencies> </sub-deployment> </jboss-deployment-structure>
Packaging libraries in a shared library is available, since Java EE 5 is commonly used for holding the JAR files that are used by all modules of the EAR.
The default name for the shared library is lib, however you can override it at any time using the library-directory element in the META-INF/application.xml file. For example, supposing you wanted to use the folder common for holding your shared library, then you could add to your application.xml:
As a side note, we suggest you to avoid placing component-declaring annotations (such as EJB3) in the shared folder, as it can have unintended and undesirable consequences on the deployment process. For this reason, we strongly recommend placing just utility classes in the shared library folder.
Using Class-Path declaration to solve dependencies:
Until now, we have solved dependencies between modules using JBoss' way, which we obviously suggest as first choice. Nevertheless, we should account also for Java's portable way to reference one or more library included in the EAR file.
This can be done using the Class-Path attribute in the MANIFEST.MF file of a module, which needs to reference another library that could not be otherwise be visible to the application (think to the earlier example, of a deployment unit with isolation set to true).
For example, supposing you needed to reference the Utility.jar application from within your Web application, then simply add to your META-INF/MANIFEST.MF the following:
You can actually include more than one library to the Class-Path, keeping separated them by comma, much the same way you did with the JBoss' Dependencies attribute.
Unlike the Dependencies attribute, the Class-Path attribute points to the actual JAR file name (and not the module name) to reference dependant libraries.
Choosing between Class-Path approach and JBoss' Dependencies approach is a matter of how your application is structured: by using JBoss' Dependencies buys you a richer set of options, in particular the ability to export the Dependencies to other deployments, as we have shown earlier. One more point in favor of the JBoss' Dependencies approach, is the ability to reference modules, which are not actually packaged within the application; for example, we have seen how to add a dependency to log4j Api, which are part of the server distribution.
On the other hand, the main advantage of the Class-Path approach relies on application portability. Thus, if a full-portable solution is a priority for you, you could consider switching to the Class-Path manifest attribute.
Taken from JBoss AS 7 Configuration Deployment and Administration Book.
Learn JBoss AS 7 quickly !
- << Prev