ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Using the Jakarta Commons, Part 2

by Vikram Goyal
07/09/2003

Jakarta Commons is a Jakarta subproject that creates and maintains independent packages unrelated to any other framework or product. The packages are collections of components that serve small useful purposes in their own right and are usually server-centric.

The previous installment of this series divided these components into five categories and described the Web and Trivial categories. This article describes the XML and Packages categories. The final installment will cover the Utilities category. Note that these categorizations are purely for organizational reasons.

Packages Category

The Packages category contains the Codec and Modeler components.

Codec

Summary: Provides implementations of commonly used encoders and decoders.

Where: Main Page, Binaries, Source.

When: When you want a standard implementation of the Base64 and Hex encoding mechanisms.

Example Application: CodecDemo.java, needs commons-codec-1.1.jar in the CLASSPATH.

Description:

Source Code

Download all of the example code in one zip file.

The classes in the Codec component are divided into two packages. One is a pure implementation of the commonly used Base64 and Hex encoding mechanisms; the other contains the encoding mechanisms for language and phonetic encoders. Since the usage of the language and phonetic encoders is not so common, I will give examples of the first package only. The usage is similar for both packages.

Base64 encoding is primarily used in the transfer of email. The RFC that defines the transfer of MIME documents specifies Base64 encoding, so that arbitrary binary data can be transferred safely using only the printable ASCII character set. For example, if you have an image that needs to be transferred using email, your email client will use Base64 encoding to convert this binary data into ASCII. Using this encoding, triplets of 8-bit octets are encoded as groups of four characters, each representing 6 bits of the source 24 bits. The encoded string is 1.3 times the size of the original. The = character is used to pad the end of the file. Besides MIME documents, this encoding is also used for encoding the user:password string in an HTTP Authorization header in BASIC Authorization.

Using Base64 is pretty simple. Use the static methods of the Base64 class: Base64.encodeBase64(byte[] byteArray) and Base64.decodeBase64(byte[] byteArray). You can also use a static method, Base64.isArrayByteBase64(byte[] byteArray), to determine if a given byte array would pass the Base64 test for correctly encoded data (since it should only contain printable ASCII characters).

byte[] encodedBytes  = Base64.encodeBase64(testString.getBytes());
String decodedString = new String(Base64.decodeBase64(encodedBytes));
System.err.println("Is \'^\' a valid Base64 character? " 
      + Base64.isArrayByteBase64(invalidBytes));

Using the Hex encoder and decoder is similar and serves the purpose of encoding/decoding data bytes to and from their hexadecimal equivalents.

Modeler

Summary: Provides support for configuring and instantiating Model MBeans (Management Beans) according to the JMX (Java Management Extensions) specification.

Where: Main Page, Binaries, Source.

When: When you want to create and manage the Model MBeans that let you manage your application using a standards-based management API.

Example Applications: ModelerDemo.java, DemoManagedBean.java and mbeans-descriptors.xml require commons-modeler-1.0.jar, commons-logging.jar, commons-digester.jar, commons-collections.jar, commons-beanutils.jar, and the Reference Implementation of the JMX, jmxri.jar, available from Sun, in the CLASSPATH.

Description:

Please note that the following discussion requires that you have a working understanding of the JMX API.

Managed Beans (Management Beans or MBeans) are the beans that get associated with the components in your application that you wish to manage. Model MBeans are a special type of MBeans that are highly dynamic and configurable and require metadata information about the classes that are being managed (as opposed to managed classes implementing interfaces). The Modeler provides a set of functions that can make your job of supplying this metadata information easier, through an XML interface. Further, the Modeler provides a registry and a base Model MBean to work with.

Using Modeler is relatively simple. Modeler allows you to create the metadata information required for your Model MBeans in the form of an XML file. This XML file must conform to a DTD supplied with the Modeler. This metadata is used to create the registry at runtime. This registry is the central repository of all your Model MBeans that are managing your managed beans. It acts as a factory for these beans.

Let us start by creating this XML file for a targeted Managed Bean, called DemoManagedBean. This managed bean has an attribute called name that can be read and written.

<?xml version="1.0"?>
<!DOCTYPE mbeans-descriptors PUBLIC
"-//Apache Software Foundation//DTD Model MBeans Configuration File"
"http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd"> 

<!-- Descriptions of JMX MBeans -->
<mbeans-descriptors>
    <mbean name="ManagedBean" description="Example Managed Bean" type="ManagedBean">
        <attribute   name="name" description="Simple Name" type="java.lang.String" />
        <constructor name="ManagedBean"/>
    </mbean>
</mbeans-descriptors>

As you can see, this file provides information about the ManagedBean, including its attributes, constructors, and, even though this is not shown in this example, its operations. This is our metadata information. You can specify the class name for the Model MBean as an attribute of the mbean element if you intend to extend the base MBean, called BaseModelMBean, supplied with Modeler:

<mbean name="ManagedBean" className="MyExtendedManagedBean"
    description="Example Managed Bean" type="ManagedBean">

The standard Model MBean, as specified above, simply passes on all of the calls directly to the ManagedBean class.

Next, we will supply this information to the registry. Note that after loading the registry with the descriptor file, a static method allows us to retrieve the fully formed registry.

// create the registry
Registry registry = null;
try {
    URL url = ModelerDemo.class.getResource("mbeans-descriptors.xml");
    InputStream stream = url.openStream();
    Registry.loadRegistry(stream);
    stream.close();
    registry = Registry.getRegistry();
} catch (Throwable t) {
    t.printStackTrace(System.out);
    System.exit(1);
}

After creating the registry, we need to create a Model MBean and register it with the default managed server. This will allow any JMX clients to call functions on the managed bean through the Model MBean. These steps are illustrated in the following two tables:

 // get a handle on a managed bean instance
DemoManagedBean mBean = new DemoManagedBean();

// create a Model MBean and register it with the MBean server
// using the instance of the mBean
MBeanServer mServer = registry.getServer();
ManagedBean managed = registry.findManagedBean("ManagedBean");

try {
	ModelMBean modelMBean = managed.createMBean(mBean);
	String domain         = mServer.getDefaultDomain();
	ObjectName oName      = new ObjectName(domain + ":type=ManagedBean");
	mServer.registerMBean(modelMBean, oName);
} catch(Exception e) {
	System.err.println(e);
	System.exit(0);
}

try {
    ObjectName name =
        new ObjectName(mServer.getDefaultDomain() + ":type=ManagedBean"); 
    ModelMBeanInfo info = (ModelMBeanInfo) mServer.getMBeanInfo(name);
    System.err.println(" className="       + info.getClassName());
    System.err.println(" description="     + info.getDescription());
    System.err.println(" mbeanDescriptor=" + info.getMBeanDescriptor());
    System.err.println("================================================");
    System.err.println("Original Value of Name: " +
        mServer.getAttribute(name, "name"));
    mServer.setAttribute(name, new Attribute("name", "Vikram"));
    System.err.println("New Value of Name: " +
        mServer.getAttribute(name, "name"));
} catch(Exception e) {
    System.err.println(e);
    System.exit(0);
}

Although this example might seem trivial, it illustrates the value of using Modeler. Contrast this with the steps you would have to take for creating a similar Model MBean without the Modeler. Using an XML file for describing the ModelMBeanInfo is powerful and extensible, and a much better approach than hardcoding the information.

Pages: 1, 2

Next Pagearrow