kapok

垃圾桶,嘿嘿,我藏的这么深你们还能找到啊,真牛!

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  455 随笔 :: 0 文章 :: 76 评论 :: 0 Trackbacks

Packaging and Application Deployment(Page583-610)

      1.As application servers use different approaches to class loading, we may need to package applications
differently for different application servers.Even standard deployment units such as EARs may not be wholly
portable.We'll also need to follow server-specific conventions to define resources such as JDBC DataSources,
which applications require. As we'll see, the standard J2EE deployment descriptors do not provide all
necessary information, meaning that we normally require additional, proprietary, deployment descriptors.
Although the J2EE specifications describe the structure of standard deployment units, no standard deployment
process is (as yet) mandated.

        2.The two most commonly used deployment units in J2EE applications are Web ARchives (WARs) and EJB
JAR files.

         3.Most servers allow deployment units to be deployed in "expanded" or "exploded" form.

      4.
o How we package applications, and especially where we include classes used by both EJB
JAR and WAR modules.
o Portability between application servers. Differences between class loading behavior in
different application servers can be a real problem for portability, and can mean that an EAR
that works on one server may not work in another, even if it is coded within the J2EE
specifications.

5.
Let's first look at how Java 2 class loading works. The following two basic principles will always apply:
o Each class retains an association with the class loader that loaded it. The getClassLoader()
method of java.lang.Class returns the class loader that loaded the class, which cannot be changed
after the class is loaded. This is the class loader that will be used if the class attempts to load classes
by name.
o If the same class is loaded by two class loaders, classes loaded by the two class loaders will not be type
compatible (although serialization will work).

The documentation of the java.lang.ClassLoader class further defines the following behavior for class
loaders:
o Class loaders are hierarchical. When a class loader is asked to load a class, it first asks its parent class
loader to try to load the class. Only if the parent (and parent's ancestors) cannot load the class, will
the original classloader attempt to load the class. The top of the class loader hierarchy is the
bootstrap loader built into the JVM, which loads java.lang.Object().
o Although a class loader can see classes loaded by its parent(s), it cannot see classes loaded by its
children
.
As it's possible to implement a custom class loader (and most application servers provide several), it is
possible to depart from the hierarchical behavior described in the last two bullets.


6.
J2EE servers use multiple class loaders, largely because this allows dynamic application reloading. Clearly
we don't want to reload all the application server's own classes on redeploying an application. This would
mean that the application server would always need to be restarted. So application servers use different class
loaders for application code to those they use for their own standard libraries
, for example. Typically one or
more new class loaders will be created for each application deployed on a server.

However, multiple class loaders are not usually used for different application-specific classes in the same
application unless we use EJB (JSP pages may be given a separate class loader, but this doesn't usually affect
application code).
As I've previously mentioned, using EJB considerably complicates the deployment model, compared to that for a
pure web application. This is also true of class loading. In a WAR, we can simply include all binary dependencies
in the /WEB-INF/ lib directory. However, things get more complicated when WARs access EJBs.

To see why, let's consider a common approach to implementing class loading in application servers. In an
application deployed as an integrated enterprise application in an EAR, the EJB class loader is often the parent
of the WAR class loader
. Orion and WebLogic, for example, both use this approach. This is a natural
implementation approach, as WARs will typically access EJBs (and therefore need to be able to see at least
EJB client classes), while EJBs do not access web components.

However, it's not the only valid implementation approach, so the following discussion
doesn't apply to all application servers.

Assuming standard J2SE hierarchical class loading behavior, such a hierarchy will mean that any class can
access classes in boxes that enclose its class loader. However, classes associated with the outer boxes cannot load
classes in the inner boxes. Thus web application classes can see classes deployed in the application's EJBs and
system classes. However, EJB classes cannot see web application classes, and classes installed at server-wide
level cannot see any application-specific classes
.


7.
Surely this is all of interest only to implementers of J2EE application servers? Unfortunately, application
developers can't afford to ignore, or be ignorant of, the implications of J2EE class loading.

Assuming the class loader hierarchy described above, let's consider a plausible scenario. Imagine that an
application class or a framework class used in both EJB and web components attempts to load a class within a
WAR. Imagine, for example that a BeanFactory implementation used in the EJB container is also used by
code within a WAR to load classes by name and manipulate them. Even though this infrastructure class is
visible in the WAR, it cannot load WAR classes. Since it was loaded by the EJB class loader it cannot see
classes in the WAR, which were loaded by a descendant class loader.
We can't always solve this problem simply by holding class definitions in both WEB and EJB JAR file, because
this may cause class cast exceptions, if the two class loaders end up independently loading one or more classes.

Thus there are two basic problems relating to J2EE class loading, in the common case where EJB and web
modules are included in the same enterprise application:
o Where do we hold the definitions of classes used in both EJBs and web applications?
o How do we ensure that two class loaders don't end up holding independent versions of the same
class, resulting in class cast exceptions?

8.
Not only do implementations of class loading differ, but different J2EE specifications differ regarding
class loading.

The Servlet 2.3 specification (9.7.2) states that "It is recommended also that the application class loader (这里是不是专指web 容器的class loader啊)be
implemented so that classes and resources packaged within the WAR are loaded in preference to classes and
resources residing in container-wide library JARs".
This clearly conflicts with the standard J2SE class loading behavior, as described in the Javadoc for the
java.lang.ClassLoader class. As the WAR class loader must be a dynamic class loader, it must be the child of
another class loader provided by the application server. Hence the Servlet 2.3 recommendation is the opposite of
normal Java 2 class loading behavior, which clearly states that classes will be loaded from the child class loader (in
this case the WAR class loader) only if they cannot be resolved by the ancestor class loaders.

The main merit of Servlet 2.3-style class loading is that it can allow us to ship any patched libraries an
application requires as part of the application, without altering the server installation. For example, the XMLC
2.1 web content generation technology discussed in Chapter 13 requires patched versions of XML libraries
shipped with some application servers. With Servlet 2.3 class loading, we can include the necessary patches in
the /WEB- INF /lib directory, without any need to modify overall server configuration or any risk of conflict
with other applications.

9.
We also need to take into account further J2SE class loading refinements. Changes in J2SE 1.3 make it possible
for JAR files to specify dependencies on other JAR files, by specifying a space-separated list of relative file
paths in a Class-Path header in their /META-INF/MANIFEST.MF file. Section 8.1.1.2 of the J2EE 1.3
specification requires that application servers support this for EJBJAR files. The following example from the
sample application's ticket-ejb.jar file's MANIFEST.MF file illustrates the use of this mechanism in the
sample application:
Class-Path: Iog4j-1.2.jar 121-core.jar 121-ejbimpl.jar 121-jdbc.jar

This declares that the application-specific classes in the ticket-ejb.jar file depend on four infrastructure
JARs, meaning that the EJBJAR file doesn't need to include any third party classes. These paths are relative. All
these JAR files are included with the EJBJAR file in the root directly of the application EAR, as the following
listing of the EAR's contents shows:
META-INF/
META-INF/MANIFEST.MF
META-INF/application.xml
121-core.jar
i21-ejbimpl. jar
121-jdbc.jar
ticket-ejb.jar
ticket.war
Iog4j-1.2.jar

NOTE: If you use the extension mechanism in a J2SE application, the Class-Path manifest entry can reference directories, too. But for J2EE applications that are wholly contained within JAR files, the Class-Path manifest entry can only reference other JAR files.

The extension mechanism is a nice capability, especially since it is designed to handle circular redundancies by creating a unified class path containing all dependencies in first parsed-based ordering. For example, if the first EJB application parsed is EJB1.jar and it references:

Class-Path: jaxp.jar EJB2.jar xmlx.jar

A classloader will then parse EJB2.jar that references:

Class-Path: jaxp.jar EJB1.jar

The resulting "application" class path that a classloader would ultimately use would be:

Class-Path: jaxp.jar EJB2.jar xmlx.jar EJB1.jar


Section 8.1.1.2 of the J2EE specification does not require the resolution of classes external to the EAR file, such
as libraries installed at a server level. This may work in some servers, but is non-standard. If an application
depends on external binaries, it's usually better just to use your server's way of installing binaries at server-wide
level. (This is also non-portable, but simpler.)

Reference:  EJB 2 and J2EE Packaging  http://www.onjava.com/lpt/a/onjava/2001/06/26/ejb.html

Currently, the J2EE 1.3 specification defines an enterprise application packaging unit to be a JAR file with an .ear extension. EAR files can contain one or more:

  • EJB modules (.jar extension)
  • Web application modules (.war extension)
  • JCA resource adapter modules (.rar extension)
  • Application client modules (.jar extension)

Since most web-based J2EE applications are composed of web and EJB applications, the EAR file meets the basic requirements for packaging an application. However, it is lacking in capability for packaging complicated J2EE applications. For example, the following components are often used in a J2EE application, but cannot be declared in an EAR file:

  • Some JMS consumers that run within an application server, such as a MessageConsumer that runs as part of a ServerSession
  • JDBC DataSource objects
  • JMS ConnectionFactory and Destination objects
  • JMX MBeans
  • Startup and shutdown classes (admittedly, a propriety extension provided by vendors, but generally unilaterally supplied by all vendors)

Currently, all of these components of an application have to be manually configured and deployed through a vendor's administration interface. As the usage of the items listed above increases over time, it will become more important for EAR files to natively support packaging of these components to achieve true J2EE application portability

The most frequent question raised about J2EE packaging is in regards to utility and support classes.


 

posted on 2005-04-05 09:53 笨笨 阅读(251) 评论(0)  编辑  收藏 所属分类: J2EEALL

只有注册用户登录后才能发表评论。


网站导航: