Novell is now a part of Micro Focus

How to Build J2EE Applications Using Novell Technologies: Part 4

Articles and Tips: article

J. Jeffrey Hanson
Chief Architect
Zareus Inc.
Jhanson583@aol.com

01 Aug 2002


This AppNote is the fourth in a series that outlines a platform and methodology for Java 2 Platform Enterprise Edition (J2EE) application development on NetWare using a service-oriented architecture. In this AppNote we further explore the business tier and introduce how our services interact with a platform kernel. We also introduce how the Java Management Extensions (JMX) provide a powerful foundation on which to build a kernel.


Topics

Java application development, J2EE, Java Management Extensions (JMX)

Products

Java 2 Enterprise Edition

Audience

developers

Level

intermediate

Prerequisite Skills

familiarity with Java programming

Operating System

n/a

Tools

none

Sample Code

yes

Introduction

This is the fourth in a series of AppNotes outlining a platform and methodology for Java 2 Platform Enterprise Edition (J2EE) application development on NetWare using a service-oriented architecture.

In the previous AppNote we discussed how our platform uses XML-configurable components and services to allow maximum flexibility and extensibility. We introduced our service-oriented business tier and discussed the technologies used to communicate from the Web tier to the business tier.

In this AppNote, we will further explore the business tier and introduce how our services interact with a platform kernel. We will also introduce how JMX provides a powerful foundation on which to build our kernel.

Charging into Battle with the Kernel

Distributed enterprise platforms, such as J2EE, are complex beasts, consisting of many different kinds of resources that are constantly changing. These resources are often instantiated dynamically, distributed across network hosts, modified in real-time, clustered in real-time, and uneventfully destroyed. This unpredictably dynamic personality presents an immediate demand for a powerful and manageable foundation for these resources. We will call this foundation "the kernel."

The kernel is the focal point of the platform, especially as far as the business tier and services are concerned. The kernel provides mechanisms for services to be dynamically added and removed, and also manages relations and communications between services. This ensures that each service interacts with other services securely and efficiently within a managed domain.

We will use the Java Management Extensions as the primary technology to build the kernel for our platform.

JMX and the Kernel

The Java Management Extensions (JMX) specification defines an architecture, a set of patterns and APIs for instrumenting and managing resources (components, services, configuration files, applications, and so on) in Java. JMX standardizes the management of these resources, known as managed beans or MBeans, by unifying them within an open and extensible architecture. Because it is based on a model that separates management interfaces from implementation details, JMX promotes efficient object-oriented practices.

Some notable benefits that JMX provides are:

  • Transparent handling of remote communications between clients and servers

  • Management of application and platform resources are handled proactively

  • Real-time monitoring and resource reloading

  • Hot-deployment of resources

  • Use of generic administration tools to manage components at runtime

  • Elimination of the need for manual administration of multiple configuration files and property files

Our kernel uses JMX for management of all components. Each component registered with our kernel automatically becomes manageable by any JMX-aware management tool. We will make extensive use of this relationship between components and the kernel to provide a registry and lifecycle manager for our services.

The kernel will provide mechanisms for services to be dynamically added, dynamically removed, and dynamically updated. The kernel will also provide a mechanism to create inter-service relationships. Our kernel provides a "sandbox" that each service plays in, ensuring that they behave in a well-defined, secure, and efficient manner.

The Three Layers of JMX

JMX is designed as three layers: instrumentation, agent, and distributed services. The instrumentation layer concerns itself with exposing resources as MBeans. An MBean can be defined as anything that can be represented as a Java object. The agent layer concerns itself with managing the communications, storage, and lifecycle of the MBeans. The distributed services layer concerns itself with how remote clients connect to agents. This remote communication mechanism involves entities such as protocol adapters and connectors.

Instrumentation Layer and MBeans

Managed resources, according to the JMX specification, are called managed beans or MBeans. MBeans are ordinary Java classes that are instrumented with a common management interface and are exposed by agents to interested applications, tools, and services. MBeans can instrument their management interface either statically or dynamically. Statically instrumented MBeans are called Standard MBeans. Standard MBeans expose their management interface by implementing an interface that follows the pattern of "classnameMBean.java". In other words, if you have a class myclass.java that you want to instrument to be manageable, you must provide an interface named myclassMBean.java that exposes the attributes and operations that you want managed.

The following code snippet shows a Java class named User and its accompanying MBean interface:

public class User implements UserMBean

{

    private String   name = "";

    private String   password = "";

    private String   address = "";

    private String   city = "";

    private String   state = "";

    private String   zip = "";                    

    private String[] phoneNumbers = null;

    

    public String getName()

    {

        return name;

    }

    

    public void setName(String newValue)

    {

        name = newValue;

    }

    

    public void setPassword(String initialValue)

        throws Exception

    {

        if (password.length() > 0)

        {

            throw new Exception("Password exists. "

                                        +"Use changePassword method to modify it.");

        }

    

        password = initialValue;

    }

    

    public String getAddress()

    {

        return address;

    }

    

    public void setAddress(String newValue)

    {

        address = newValue;

    }

    

    public String getCity()

    {

        return city;

    }

    

    public void setCity(String newValue)

    {

        city = newValue;

    }

    

    public String getState()

    {

        return state;

    }

    

    public void setState(String newValue)

    {

        state = newValue;

    }

    

    public String getZip()

    {

        return zip;

    }

    

    public void setZip(String newValue)

    {

        zip = newValue;

    }

    

    public String[] getPhoneNumbers()

    {

        return phoneNumbers;

    }

    

    public void setPhoneNumbers(String[] newValue)

    {

        phoneNumbers = newValue;

    }

    

    public boolean changePassword(String name,

                                    String oldPassword,

                                    String newPassword)

    {

        if (this.name.equals(name) == false)

        {

            return false;

        }

        if (this.password.equals(oldPassword) == false)

        {

            return false;

        }

        if (oldPassword.equals(newPassword) == false)

        {

            return false;

        }

        password = newPassword;

        return true;

    }

}

    

public class User implements UserMBean

{

    public String getName();

    public void setName(String newValue);

    public void setPassword(String initialValue)

    throws Exception;

    public String getAddress();

    public void setAddress(String newValue);

    public String getCity();

    public void setCity(String newValue);

    public String getState();

    public void setState(String newValue);

    public String getZip();

    public void setZip(String newValue);

    public String[] getPhoneNumbers();

    public void setPhoneNumbers(String[] newValue);

    public boolean changePassword(String name,

                                        String oldPassword,

                                        String newPassword);

}

As you can see by the implementation of our User class, we have a number of read/write attributes (accessor methods prefixed with get or set), one operation (changePassword), and one read-only attribute: password. The password is read-only because we do not expose a setter method to alter its value.

Agent Layer

The agent layer provides access to all of the MBeans that are registered with each individual agent. The agent layer provides additional standard services that are also registered as MBeans. These standard services include dynamic loading, timers, relations, and monitoring. The primary component of the agent layer is the MBean server, which provides the services for storing and manipulating MBeans.

Agents handle all communications between clients and MBeans. Agents are software components that control MBeans by storing aliases to them in the MBean server registry. This third-party interaction between clients and MBeans creates an abstraction layer between the two which allows MBeans to be modified or replaced at runtime without interrupting the application environment.The following is an example of a simple agent that registers three objects as MBeans and exposes one method that returns a list of the names for these MBeans:

import javax.management.ObjectName;

import javax.management.MBeanServer;

import javax.management.MBeanServerFactory;

import java.util.Set;

import java.util.Iterator;

    

public class MyCompanyAgent

{

    public void initialize()

        throws Exception

    {

        MBeanServer server = MBeanServerFactory.createMBeanServer();

    

        // Typically these are dynamically discovered from a

        // configuration source or added programmatically by external

            // clients

    

        server.registerMBean(new User(),

                                    new ObjectName("MyCompanyDomain:name=user"));

        server.registerMBean(new Accounts(),

                                    new ObjectName("MyCompanyDomain:name=accounts"));

        server.registerMBean(new Portfolio(),

                                    new ObjectName("MyCompanyDomain:name=portfolio"));

    }



    public Iterator getMBeanNames()

    {

        // passing null as args to the queryNames method retrieves all names

        Set names = server.queryNames(null, null);

        return names.iterator();

    }

}
Distributed Services and the Kernel

Services form the core of any enterprise application. They are software entities exposing a public interface that defines a group of common operations. Services don't maintain request-specific information, but they do support dynamic lookup and discovery and have the ability to be invoked by any client. The set of functionality provided by the service is represented in methods/operations. These methods can take input parameters and generally return responses. Services may have global properties, but should not provide getters or setters for modifying these properties.

The kernel is responsible for managing the services. Services can be dynamically added or removed from the kernel. Service developers can focus on developing the logic for their services, without concerning themselves with manageability issues. The kernel manages the lifecycle of all services, providing a completely dynamic architecture for services. As a service is added to the kernel, it immediately becomes available to the application.

Horizontal Domain Services

JMX defines standard services that handle tasks such as event scheduling, dynamically loading components and services, monitoring components and services, and creating relationships between components and services. We will eventually exploit these services to form the remaining infrastructure for our platform.

In addition to the JMX-provided services, our platform supports domain-neutral services. A domain-neutral service is one that can be shared across multiple vertical domains; thus we refer to them as horizontal domain services. Some examples of these types of services include scheduling, alerts, user/group management, logging, business rules, and others.

Installing JMX on NetWare

Installing JMX simply involves downloading an implementation of the specification and adding a startup file that places the appropriate .jar files in NetWare's classpath and then runs the main class for the implementation. For example, the following is an NCF file that runs most JBoss 2.x implementations:

envset JBOSS_HOME=sys:/jboss-2.2.2

envset cwd=$JBOSS_HOME/bin

envset JBOSS_CLASSPATH=$JBOSS_HOME/bin/run.jar

envset JBOSS_CLASSPATH=$JBOSS_CLASSPATH;$JBOSS_HOME/lib/crimson.jar



java -verbose -Djavax.xml.parsers.DocumentBuilderFactory=

    org.apache.crimson.jaxp.DocumentBuilderFactoryImpl

    -Djavax.xml.parsers.SAXParserFactory=

    org.apache.crimson.jaxp.SAXParserFactoryImpl 

    -classpath $JBOSS_CLASSPATH org.jboss.Main %1 %2 %3 %4 %5

Implementations that run on NetWare can be found at JBoss.org and on Sun's Web site. You can download the reference implementation binaries (.jar files) and source code files from the links to the JBoss implementation and Sun's reference implementation, given at the end of this AppNote.

Conclusion

This AppNote has explored the business tier in more depth and introduced how our services interact with the kernel. We also introduced how JMX provides a powerful foundation for our kernel to build on.

The next AppNote in this series will further explore the kernel and some of the other services that JMX offers to empower our platform.

For Additional Information

For more information about the technologies discussed in this AppNote, refer to the following resources.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates