© 2001 International Business Machines Corporation. All rights reserved.
When developing applications within the J2EE framework, you often need third-party or utility classes. You can store these classes in a variety of locations so that they can be used by the rest of the modules in the application. This article explores the advantages and disadvantages of each location, and explains why these classes are usually packaged as JAR files and placed in one of only two locations.
If the same team that is developing the J2EE application is also developing the utility classes, the next questionis how both sets of code can be managed, built, and tested within the same workbench. Within WebSphere Studio Application Developer, you can create the utility classes in a Java#x2122 project, but how can these classes be periodically jarred up and placed in another location? Since Application Developer is built on top of the highly extendable open-source Eclipse project, this is not a problem. This article presents a simple plug-in that you can use to periodically or automatically zip up a Java project into a JAR file within another project.
Note: The attached plug-in is not part of WebSphere Studio Application Developer and is only provided as a sample of the extensible nature of the product. It is not officially supported and you should read the full license agreement before downloading. Use at your own risk.
Where should utility classes go?
Exploring the application server and the J2EE specification reveals five places where classes can be stored so that they can be found by the modules within a J2EE application. Each of these locations is discussed below, as well as whether each location is applicable to utility classes.
- As loose classes within a Web module's
WEB-INF/classesfolder. These classes are visible only within the same Web module, and this is usually not a valid location because the classes may not have anything to do with the Web module that contains them.
- As a JAR file within a Web module's
WEB-INF/libfolder. This is a good place to put utility classes used by the Web module. However, since these JAR files are only visible from within the Web module, this is not a good place for JAR files that are used by multiple modules.
- As loose classes within an EJB module. Although these classes are visible from within other modules that use a manifest file, this is also a weak solution, because the utility classes may not have anything to do with the other code contained in the EJB module.
- As JAR files or loose classes on the application server's global classpath.
This appears to be an easy solution, since it makes the utility classes visible
to any modules running on the server. However, you should avoid this technique
for four reasons.
- Portability - By placing the code outside of the application server, these classes or JAR files must be copied along with the application. This technique also requires changing the global classpath of each server it is deployed to. Because each application server has different classloaders and this falls outside the J2EE specification, each server type may require these classes to be handled differently.
- Visibility - This technique makes the classes visible to all applications running on the server. Even if the classes are only required by a single application, other applications can inadvertently use them.
- Maintainability - This technique forces all applications running on the server to use the same version of the classes. If one application is upgraded to a newer version of the classes, all of the other applications must be upgraded and/or retested.
- Compatibility - This technique does not let an application use a different version of any classes that are used by the application server or other applications.
- As a JAR file within the Ear application. These classes are visible to any module within the application that is using a valid manifest file. This is usually the best solution, as it keeps the classes packaged in their own JAR file, which is usable by any modules within the application. This solution does not suffer from any of the problems of using the global classpath.
For the reasons above, you should usually package utility classes as JAR files and place them in the WEB-INF/lib folder, or more likely, directly in the Enterprise Application. However, what happens if the same team that is developing the J2EE application is also developing these classes? Inside Application Developer, Java projects are used to create and build utility classes, and it is awkward to continually zip up these projects and then import the JAR file back into the EAR project. As the utility classes change within the Java project, it's cumbersome to rebuild and maintain the EAR project so that testing can continue.
If work on the utility classes is just starting, then the
simplest solution is probably just to put the folder containing the compiled
classes on the global classpath of the application server (or perhaps
in the case of WebSphere). This allows rapid development and may provide an
adequate temporary solution. However, as the classes mature, you should use
the JAR file approach for the reasons given above, and to ensure that your application
will continue to run correctly when deployed to a production server.
As another solution, the rest of this article presents a simple plug-in that you can use to automatically create and maintain a JAR file within one project by zipping up the contents of another project. This can greatly simplify the J2EE development process while staying within the bounds of the J2EE specification.
A J2EE development scenario
Figure 1 below shows a typical J2EE application, which consists of an EAR, EJB, Web, and Java project. Both the Web and EJB projects need to use utility classes, and these classes are currently being developed within the Java project.
Figure 1. A typical J2EE application
As discussed above, the best way for the EJB and Web projects to use these classes is to create a JAR file within the EAR. By modifying the manifest file of the EJB and Web projects, they can use the JAR file at run time, and continue to be fully portable to any J2EE application server without any additional steps.
Figure 2 below shows the end result, with a JAR file created in the EAR project. But how do you create and maintain the JAR file out of the build directory of the Java project? If both the J2EE and Java projects are being developed simultaneously, keeping these in sync can become a major problem.
Figure 2. Using a JAR file from an EAR
The attached plug-in provides a builder that automatically zips up the contents of the Java project's build directory whenever any classes are added, modified, or removed. Once you tell it where to create the zip file, development can continue and the utility JAR file will be kept in sync with the contents of the Java project.
Installing the zip creation plug-in
To install the zip file creation plug-in, following these steps:
- Download zipCreation.zip below.
- Extract the download file into the
Application Developer installation/pluginsfolder.
- Verify that a new
Application Developer installation/plugins/com.ibm.sample.zip.creationfolder has been created during the unzipping.
Using the zip creation plug-in
To use the plug-in, take the following steps for each Java project that should be zipped into a JAR file.
- From within the Navigator view, right-click on the Java project and select Properties.
- Select Zip Creation from the list on the left side of the dialog.
- If you want zip file creation to be automatic, select Enable. This will cause the zip file to be created each time the contents within the current project change. If you don't want zip file creation to be automatic, right-click on the project and select Update zip file(s) on the project's popup menu whenever you want to update the zip file.
- Ensure that the Workspace option is selected and click Browse.
- Select the EAR project within the workbench. Click OK.
- Type a new filename in the Filename field. For example,
- Your dialog should now be completed as shown in Figure 3 below. Click OK.
Figure 3. Zip creation properties
If you take a look in the EAR project, you will see a new JAR file created. As you continue to make changes to the Java project, these changes will be reflected in the JAR file.
For each EJB or Web project that needs to use the JAR file, you will need to update the manifest and the Java build classpath to use this new JAR file. You can do both of these steps at the same time using the Edit Module Dependencies dialog. Follow these steps.
- Right-click on the EJB or Web project, and select Edit Module Dependencies.
utility.jarfrom the checkbox list as shown in Figure 4 below.
- Click OK.
Figure 4. Edit Module Dependencies dialog
To disable the zip file creation or change the settings, just reopen the project's properties and change the options. This plug-in can be used in many other cases, and is not limited to this scenario. You can also create zip files outside of the workbench, and you can add other source folders, to include source or other resources within the created zip file.
By looking at the various places where utility files can be
used by a J2EE application, we found that it is usually best to put utility
classes in a JAR file in the
or directly in the Enterprise application. If the utility classes are used by
multiple modules (or even a single EJB module), always use the Enterprise application.
We then described the unsupported zip creation plug-in as one solution to the
problem of co-developing utility classes and J2EE applications within the same team.
Questions from users
Really good article, but two problems:
- With Application Developer 5.0, when I installed the zip creation plug-in, it's impossible to view the zip creation function after right-clicking on a Java project in the J2EE navigator view or elsewhere. I can see the zip creation function only for Web and EJB modules. Is this a bug?
- In this article, we learned about how modules can see utility classes. But how do utility classes see each other? Or, if you prefer, how does a utility class in one package use a utility class in another package?
Thank you for all of your teaching. -- Eric
Response from author
- Sorry, but as explained in the instructions, the zip creation properties are available only via the resource Navigator.
- Do you mean within a single JAR, or between two JARs? At compile time, you can set up whatever you want by using the Java build path for the project. At run time, within a single JAR, the regular Java visibility rules are followed. With multiple JARs, utility classes can see each other by having a valid manifest file in the JAR that points to the other JAR. For information on manifest files and how they work, see the JAR specification on the Javasoft site. You can easily do this across projects, but you need to be careful, because anything outside the application and modules will not be considered part of the EAR and may not be included when an EAR is exported.
In the Web project, all of the classes are compiled to
WEB-INF/classes. Do you recommend to JAR the classes and put them
WEB-INF/lib? If so, does WebSphere Studio V5 also need to install the zip creation plug-in to JAR the classes?
Response from author
All classes that you are actively developing as part of the Web project get compiled into
and that is the correct place for them. Third party JARs, or utility JARs used by the project, can just be dropped into
WEB-INF/lib. These are the standard locations defined in the J2EE spec.
If you are developing a utility JAR to be used by the Web project, then you can create a Java project to develop the contents.
If you are using WebSphere Studio V5.0 or later and you are going to run these in the WebSphere Test Environment,
then you can use the utility Java project support (see the online help) to map the project as if it were a JAR
contained within the Web project's
WEB-INF/lib directory. Otherwise, you can periodically JAR the Java project up
and put it in
WEB-INF/lib, or use the zip creation plug-in.
This JAR file is excellent -- very useful. However, for my purposes it lacks a couple of useful features. I would like to:
- Automatically place source code into the JAR (as you can with the export/JAR file function).
- Make the update function available from the Package Explorer view.
- Place one JAR or ZIP file into another (I can do this, but there is no way I can see to dictate the order in which the two files would be built).
- Get the source code for the plug-in.
Response from author
- You can include source in the JAR/ZIP file in one of two ways: either put the source and compiled code in the same folder, or make use of the "source containers" option to add more folders into the JAR.
- Thanks for the suggestion -- the next time that I update the plug-in I will make it available from the Package Explorer and other views.
- Sorry, but the plug-in doesn't have any built-in support for multiple levels of JAR building. The only way that you would be able to make sure that this is working in the right order would be to turn off the automatic JAR building and use the Update option to build each JAR in turn, each time they change.
- Sorry, but this plug-in was shipped as part of an IBM product, so I am not free to distribute the source code.
To see additional user comments, click the View results button above.
|Code samples||zipCreation.zip ( HTTP | FTP )||50 KB|