How to Access J2EE Components and Resources From Different Applications or
Modules
As mentioned earlier, each deployed application and standalone module has its own
classloader, which means they are also bound by the different classloader universes.
Hence, applications and modules can have the same name, provided that they are packaged
separately.
One of the intended purposes of the classloader responsible for the deployed
applications and standalone modules is to turn these J2EE components into
self-contained units. However, it is sometimes desirable to have user-defined reusable
resources (such as EJB and Java programming language files) which can provide common functionalities across
applications. Currently, this can be achieved in the runtime of Sun ONE
Application Server 7 by:
- using the System classloader to load the resources.
- using the Common classloader to load the resources.
- packaging the resources in every application that uses them.
The classpath used by the System classloader is modifiable and can be extended
using the Administration Interface or via the server configuration file,
server.xml.
In contrast, the path to the Common classloader is pre-defined and cannot be modified.
The only way to force this classloader to load other classes is to copy jar
and zip files
into the <instance_dir>/lib directory, and to copy any .class files
into the <instance_dir>/lib/classes directory.
The application server will need to be restarted in both cases before the extra classes
are made available to all applications in the server instance.
The third approach is to package the reusable resources together with every single J2EE
application that makes use of these resources.
For an explanation of <instance_dir>, please refer to the
Sun ONE Application Server 7
Getting Started Guide.
A detailed description of the three approaches above can be found in the
Sun ONE Application Server 7
Developer's Guide.
While the above approaches are well-known techniques for solving the accessibility issue,
using the System or the Common classloaders to load the extra classes may compromise the
security of enterprise applications, as rogue classes are easily accessible by all other
applications and standalone modules deployed on the same instance of an application server.
Extending the classpaths to the classloaders may seem a practical solution to some
administrators, however, the potential risk is that all classes loaded by these
classloaders may be regarded as "trusted" without question by other developers.
Back to Top
The RMI over IIOP Protocol
Since the introduction of the EJB 1.1 specification, support for the RMI over IIOP
protocol is mandatory. This means reusable EJB components can be deployed in an
application server and the functionalities can be exposed to the same or even other application
servers via this protocol.
The mandatory support for this protocol means that:
- the Object Request Broker (ORB) component in an application server instance can access
ORBs in other application server instances in a consistent way.
- EJB components can access other EJB components remotely because they support this
protocol.
- standalone CORBA-compliant client applications (Rich clients or Application Client
Container, ACC) can access the EJB components remotely.
In other words, the CORBA open standards ensure that EJB components are interoperable
across multivendor EJB servers, multivendor ORBs, and CORBA clients written in programming
languages other than the Java programming language.
All EJB components (except those implemented the Local Interface) have to
extend the EJBObject interface, which itself extends the Remote
Interface. It is important to note that Local Interface,
(the EJBLocalObject interface) introduced in the EJB 2.0 component
architecture, does not extend the
Remote Interface. Hence, it cannot be set up to be accessed remotely.
As mandated in the EJB specifications, EJB components do not access each other directly.
When they need to do so, they use the naming services supported by the J2EE platform to discover each
other. The J2EE platform naming service cited in the specification is the Java Naming and
Directory Interface (JNDI).
In Sun ONE Application Server 7, the server provides the J2EE components with a
Context object. This object provides methods for binding and unbinding names
to objects, for renaming objects, and for listing the bindings. Specifically, the
InitialContext object is the handle to the JNDI API that both the J2EE
components and Rich Clients use for such purposes. It is important to note that JNDI
names are not bound by the classloader universes. Hence, the JNDI names must be unique.
To support a global JNDI namespace that is accessible to IIOP application clients, Sun ONE
Application Server 7 includes a J2EE platform-based CosNaming provider, which supports
the binding of CORBA references (remote EJB references). The InitialContext
object returned to the Rich Clients would then be a CosNaming provider. Sun
ONE Application Server 7 will register the JNDI names of the EJB components automatically,
so Rich Clients can look up and bind to these components at any time.
Back to Top
Remote Access to EJB Components
In a distributed environment, the RMI over IIOP support introduced in the EJB
specifications can have a direct impact on the following scenarios.
Firstly, this protocol can form part of the security strategy used to protect the
enterprise systems, as the EJB components deployed on a system are not accessible
directly to other J2EE components because of the classloaders. Secondly, this strategy
can be used to provide measures for a fault tolerance and/or recovery environment, as
developers of the EJB components can provide varied implementations that honour the
agreed Home and Remote interfaces. Last but not least, this
approach can also help to facilitate the software development effort as EJB components and
J2EE components can be developed independently, once the interfaces have been agreed and
finalised.
On the J2EE platform, stateless Session Beans are logical placeholders for grouping programs and
libraries that can be reused by other J2EE components. Reusable EJB components are simply
ordinary EJB modules that contain stateless Session Beans. However, the principles of
CORBA-distributed programming will have to be adhered to when developing the clients of
these reusable EJB components.
First, the clients (other EJB components, ORBs and Rich Clients), have to obtain the
machine names and the port numbers of the host machines, as well as the object names
(JNDI names) they need to have access to.
Next, absolute JNDI names will have to be used during the lookup instead of the extended
version. For example, if the JNDI name, java:comp/env/ejb/Test, is assigned
to an EJB, then the absolute name will be ejb/Test without the
java:comp/env prefix.
Finally, they also have to be supplied with the Home and Remote
interfaces of the reusable EJB components, together with the respective stub
classes of the interfaces.
The inclusion of the stub classes may seem redundant as CORBA-compliant
stub classes can
be generated using standard tools such as rmic. However, in Sun ONE
Application Server 7, stub classes are generated during deployment time using
a built-in proprietary tool. Hence, the stub classes have to be located and
packaged together with the rest of the files as described in the example below.
The following sections show a step-by-step example on how to configure and set up remote
EJB access between two different application servers.
The SimpleAgent_TestApp.ear J2EE application example can be downloaded from
the link in the Reference section below.
The three reusable J2EE platform EJB modules, Area_EJBModule.jar,
Temperature_EJBModule.jar and CurrencyConvertor_EJBModule.jar
can be downloaded from the links in the Reference section below.
Back to Top
Example
Introduction
In this example, there are three reusable EJB components, Area_EJBModule.jar,
CurrencyConvertor_EJBModule.jar and Area_EJBModule.jar, where
each module contains a stateless Session Bean, Area,
CurrencyConvertor and Temperature respectively. The J2EE
application, SimpleAgent_TestApp.ear, contains two stateful
Session Beans, Location and SimpleAgent.
The Area stateless Session Bean has two functions,
convertToSqKms and convertToSqMiles, to convert imperial
measurement units to metric measurement units and vice versa.
The CurrencyConvertor stateless Session Bean has one function,
convertToEuro, which returns a fixed exchange rate of US dollars to Euros.
In practice, the exchange rate is sensitive to market data and may change constantly. This
function can be modified independently of any clients or applications that make use of it,
provided that the interface is the same.
The Temperature stateless Session Bean has two functions,
convertToCelsius and convertToFahrenheit, to convert
temperatures from Fahrenheit to Celsius and vice versa.
The SimpleAgent uses Location (both stateful Session Beans) to
create, make queries to and remove holiday destination data. It also uses functions
exposed by the two reusable EJB components to enhance the service provided by the J2EE
application, SimpleAgent_TestApp.
Note that Location can be implemented as an Entity Bean alternatively so
data can be persisted using a database. Location is designed to be
implemented as a stateful Session Bean in this example, so attention can be focused on the
remote accessibility of EJB components.
For the purpose of this exercise, an instance of Sun ONE Application Server 7 Standard
Edition, server1 is installed on a machine named host1 running
the Solaris 9 Operating Environment (OE). This is the machine where the reusable EJB components will be deployed. Another
machine, host2, also running on the Solaris 9 OE, has server2, another
instance of the Sun ONE Application Server 7 Standard Edition. Default values including
port numbers are used for both installations.
The EJB modules and the J2EE application used in this example were developed and packaged
using Sun ONE Studio 5, Standard Edition software.
In addition, this example has been tested on a mixture of Platform and Standard Editions
of Sun ONE Application Server 7, and also on a mixture of operating systems
(Solaris 9 OE and Microsoft Windows 2000).
Determine the CORBA Host Name and Port Number
In order to connect to the EJB components on the server side, the CORBA clients need to
obtain the hostname, the designated port number of the server and also the names of the
EJB objects bound to JNDI (the absolute JNDI names).
The hostname in this example is host1, where Area_EJBModule.jar,
CurrencyConvertor_EJBModular.jar and Temperature_EJBModule.jar
will be deployed.
The designated port number is 3700 by default. This can be verified in a
number of ways.
During the Sun ONE Application Server 7 installation, a default ORB configuration is
created for each instance of the application server. The pre-configured IIOP listener is
named orb-listener-1; the default port for this listener is
3700. However, this port number may clash with some of the default
restrictions programmed into applications, such as firewalls, and so may have to be modified
as a result.
The easiest way to verify the port number is to use the Administration Interface. In the
panel on the left hand side, expand the node of server1, then
ORB, then IIOP Listeners and click
orb-listener-1. The port number of this listener should be displayed together
with other properties on the right hand side.
The port number can also be obtained via the command line tool, asadmin, as
follows:
host1# asadmin get --user admin_user --password admin_password
server1.orblistener.orb-listener-1.port
OR
host1# asadmin get --user admin_user --password admin_password
server1.iiop-listener.orb-listener-1.port
Substitute the appropriate administration user ID and password with
admin_user and admin_password.
Deploy the EJB Modules
The three reusable EJB components are now ready to be deployed on server1 on
machine host1.
Again, this can be done in a number of ways in Sun ONE Application Server 7. The most
common way is to deploy the modules via the Administration Interface.
In the panel on the left hand side, expand the node of server1,
Applications, and click EJB Modules. Next, click
the Deploy... button in the panel in the right hand side, click
Browse... to navigate to the EJB modules, choose
Area_EJBModule.jar and click OK to finish and
OK again to deploy the module. Repeat the same steps for
CurrencyConvertor_EJBModule.jar and Temperature_EJBModule.jar.
Another option is to deploy the EJB modules via the command line as follows:
host1# asadmin deploy --user admin_user --password admin_password --host
host1 --port 4848 --type ejb --instance server1 Area_EJBModule.jar
Substitute the appropriate administration user ID and password with
admin_user and admin_password.
How to Locate the stub Classes for the Home and Remote Interfaces
Stub classes are generated automatically during the deployment of the EJB components in
Sun ONE Application Server 7. These classes can be found in:
<domain_config_dir>/domain1/server1/generated/ejb/j2ee-modules/Area_EJBModule
<domain_config_dir>/domain1/server1/generated/ejb/j2ee-modules/CurrencyConvertor_EJBModule
<domain_config_dir>/domain1/server1/generated/ejb/j2ee-modules/Temperature_EJBModule
For an explanation of <domain_config_dir>, please refer to the
Sun ONE Application Server 7
Getting Started Guide.
The stub classes required for this example are:
_AreaHome_Stub.class
_Area_Stub.class
_CurrencyConvertorHome_Stub.class
_CurrencyConvertor_Stub.class
_TemperatureHome_Stub.class
_Temperature_Stub.class
The SimpleAgent_TestApp.ear File
This J2EE application contains an EJB module and a Web module. This application is
generated automatically using the tools available from Sun ONE Studio 5, Standard Edition.
The objective of these tools is designed for use during the test process before the EJB
components are deployed in a full-scale production environment.
The EJB module in the SimpleAgent_TestApp.ear file contains the class files
of the following:
Area's Home Interface
Area's Remote Interface
Stub for Area's Home Interface
Stub for Area's Remote Interface
CurrencyConvertor's Home Interface
CurrencyConvertor's Remote Interface
Stub for CurrencyConvertor's Home Interface
Stub for CurrencyConvertor's Remote Interface
Temperature's Home Interface
Temperature's Remote Interface
Stub for Temperature's Home Interface
Stub for Temperature's Remote Interface
SimpleAgent's Home Interface
SimpleAgent's Remote Interface
Implementation for the SimpleAgent stateful Session Bean
Location's Home Interface
Location's Remote Interface
Implementation for the Location stateful Session Bean
As mentioned earlier, the stub classes for the Home and Remote
interfaces are required, as these classes contain vital information such as instructions on
how to establish a connection to the proxy object (skeleton class) on the server side via
the RMI over IIOP protocol, and how to resolve method invocations across VM boundaries
dynamically.
If these classes are omitted, the application server will throw a
ClassCastException during runtime as the stub classes cannot be linked to
the Home Interface objects during the JNDI lookup.
How to Set Up InitialContext Lookup
In order to look up the EJB components via the RMI over IIOP protocol, the default
environment properties must be overwritten with the CosNaming naming service.
The following code segment can be found in the setSessionContext method in
the SimpleAgentBean.java file. Two new properties must be defined as below:
Properties env = new Properties();
env.put("java.naming.factory.initial", "com.sun.jndi.cosnaming.CNCtxFactory");
env.put("java.naming.provider.url", "iiop://host1:3700");
Next, these properties are passed to the InitialContext object as follows:
InitialContext ctx = new InitialContext(env);
Finally, the remote EJB components can then be located as follows:
Object obj = ctx.lookup("ejb/Area");
AreaHome areaHome = (AreaHome) javax.rmi.PortableRemoteObject.narrow(obj, AreaHome.class);
obj = ctx.lookup("ejb/Temperature");
TemperatureHome temperatureHome = (TemperatureHome) javax.rmi.PortableRemoteObject.narrow(obj, TemperatureHome.class);
obj = ctx.lookup("ejb/CurrencyConvertor");
CurrencyConvertorHome convertorHome = (CurrencyConvertorHome) javax.rmi.PortableRemoteObject.narrow(obj, CurrencyConvertorHome.class);
The hostname and possibly the IIOP port number must be changed when this example is
deployed in a different environment. The application will need to be recompiled and
repackaged as a result. The following steps show how this can be accomplished.
Extract SimpleAgent_TestApp.ear to a temporary directory, for example,
/var/tmp/ear:
host2# cd /var/tmp/ear
host2# jar xvf SimpleAgent_TestApp.ear
Extract the EJB module into another temporary directory, for example, /var/tmp/jar
host2# cd /var/tmp/jar
host2# cp /var/tmp/ear/SimpleAgent_EJBModule.jar .
host2# jar xvf SimpleAgent_EJBModule.jar
Change the hostname and/or port number in SimpleAgentBean.java in the
following statement:
env.put("java.naming.provider.url", "iiop://your_host:your_iiop_port");
Recompile SimpleAgentBean.java; make sure the library
<install_dir>/lib/appserv-ext.jar is in the classpath, for example:
host2# javac -classpath <install_dir>/lib/appserv-ext.jar:. SimpleAgentBean.java
Repackage the application file:
host2# rm SimpleAgent_EJBModule.jar
host2# jar cvf SimpleAgent_EJBModule.jar *
host2# cp /var/tmp/jar/SimpleAgent_EJBModule.jar /var/tmp/ear
host2# cd /var/tmp/ear
host2# rm SimpleAgent_TestApp.ear
host2# jar cvf SimpleAgent_TestApp.ear *
Deploy the J2EE Application
The J2EE application is now ready to be deployed on server2 on
host2.
Similar to the EJB modules, this application can be deployed in a number of ways. The most
common is to deploy the modules via the Administration Interface.
In the panel on the left hand side, expand the node of server2,
Applications, and click Enterprise Apps. Next, click the
Deploy... button in the panel in the right hand side, click
Browse... to navigate to the J2EE application, choose
SimpleAgent_TestApp.ear and click OK to finish and
OK again to deploy the application.
Another option is to deploy the J2EE application via the command line as follows:.
host2# asadmin deploy --user admin_user --password admin_password --host host2 --port 4848 --type application --instance server2 SimpleAgent_TestApp.ear
Substitute the appropriate administration user ID and password with admin_user and admin_password.
Test the Application
The SimpleAgent_TestApp application is now ready to be tested. The application
can be accessed using http://host2:88/SimpleAgent_TestApp, if the Web
server is configured to listen on port 88.
Click on the Invoke button under SimpleAgentHome to create an
instance of the SimpleAgent bean (in server2 on
host2).
Click SimpleAgent[number] inside the EJB Navigation Panel to
inspect the newly-created SimpleAgent bean instance.
Type in SYD, Sydney, Australia, 70,
4000000, 12400 for locationID, location, country, temperature
(in Fahrenheit), population and area (in square kilometers), respectively, and click the
Invoke button to the left of void createLocation.
Scroll down the Web page until the functions getAreaInSqKms,
getAreaInSqMiles, getAvgTemperatureInCelsius,
getAvgTemperatureInFahrenheit and getExchangeRate are
displayed. These functions are exported by the reusable EJB components (Area,
Temperature and CurrencyConvertor) found on server1
on host1.
Type SYD in the textfield underneath getAreaInSqMiles and
click the Invoke button to the left of it.
Note the value, 4787.64, in the Results of the Last Method
Invocation panel.
Type SYD in the textfield underneath
getAvgTemperatureInCelsius, and click the Invoke button to the
left of it.
Note the value, 21.11111111111111, in the Results of the Last Method
Invocation panel.
Type SYD in the textfield underneath getExchangeRate, and
click the Invoke button to the left of it.
Note the value, 0.8652, in the Results of the Last Method
Invocation panel. This is the hard-coded exchange rate of US dollars to Euros.
Back to Top
Summary
J2EE modules and applications are designed to be self-contained units running inside an
application server. To ensure this condition is upheld in Sun ONE Application Server 7,
each module and application is loaded into the VM via its own classloader. Hence, by
default, EJB components cannot be accessed from outside their respective classloader
universe.
To get around this in Sun ONE Application Server 7, either the classpath to the System
classloader or the Common classloader have to be modified so the EJB components can be
loaded together with the rest of the system libraries when the application server starts
up, or the modules have to be packaged together with the application that depends on them.
This is in contrast to iPlanet Application Server 6 and 6.5.
As discussed in previous sections, modifying system classpath may not be a good idea, as
it may introduce a weak link in the enterprise system. Another strategy is to set up the
reusable EJB components to be accessed indirectly via the RMI over IIOP protocol.
Since the introduction of EJB 1.1, application servers, and specifically the EJB
containers, have to support the RMI over IIOP protocol to ensure the interoperability of
different clients (EJBs deployed on same or different application servers, third party
ORBs and Rich clients), so method invocation can be resolved across different VMs.
Reusable resources includes a wide range of data formats such as Java applications, sound
files, images files and text files. The only reliable way of exposing reusable resources
in J2EE is via the use of EJB components, and in particular, stateless Session Beans.
This strategy may be deemed as inappropriate on first sight, as remote lookup may affect
the performance of the applications. However, the trade-off between performance on the one
hand and flexibility, accessibility and scalability on the other should be a conscious
design decision made by the system architects after balancing between the functional and
non-functional requirements of the enterprise systems.
Back to Top
References