devxlogo

Extend the JDK Classes with Jakarta Commons, Part I

Extend the JDK Classes with Jakarta Commons, Part I

y now, almost everyone in the Java community has heard about Jakarta Commons, the set of reusable classes that various Jakarta projects use. But did you know that these classes also are available as separate components, which you can use in your Java projects? This article is the first in a three-part series that explores the various Jakarta Commons components and presents real-world example applications to illustrate how to use them. The examples don’t only illustrate the Commons components; they are complete, modular applications that highlight the useful features you can reuse in typical Java projects.

In particular, this first installment explores the following components:

  • Validator
  • Collections
  • Chain
  • Functors
  • Lang

The article also includes complete source code that you can run by launching the test cases with JUnit for each of the examples.

Author Note: A basic knowledge of object-oriented programming (OOP) and the Gang of Four design patterns (Command, Decorator, Singleton, Factory, Chain of Responsibility, and Composite) will be very helpful for understanding the Commons components architecture and usage.

Validator

Commons Validator is the component Struts uses to validate forms in a Web application. This component is designed to validate any Java Bean, but you can use it to validate data (e.g., a domain layer object or user input to a Swing application, or XML-formatted data submitted to a Web service) as well.

In most projects I have seen, the validations are written in one of three ways:

  1. In domain objects
  2. In utility classes
  3. As custom frameworks

The first two approaches lead to bad design since developers tend to write their own copies of validation methods. The validation code gets scattered throughout the application even though its sole purpose is to log the error, throw an exception, or display it to the user. The other disadvantage is while raising error messages by reading from the resource bundle, the code written for this will be duplicated all over, though its purpose is the same for all validations.

As an example, I use Commons Validator to validate the user input to a Java Swing application. Figure 1 shows a snapshot of the GUI, which captures registration details from the user.

Click to enlarge
Figure 1. Snapshot of the Swing Application

Before getting into the details of the application’s Commons Validator usage, let’s look at some important classes to explain its design (Refer to the complete source code for a better understanding). The following classes are part of the package in.co.narayanan.commons.validator:

  • RegistrationScreen: A singleton class and the main frame, which contains other GUI components
  • Registration: A domain object that represents a user registration
  • Listeners: An adapter class for handling GUI events and delegating them to the appropriate commands
  • SubmitCommand: Uses Command pattern to represent a submit operation (The validation will be initiated from this class.)
  • RegistrationContext: Uses Mediator pattern to pass the necessary context information for the event listener and command classes
  • ValidatorEngine: Uses Commons Validator to validate the Registration bean and processes the result

The objective of this example is to validate the ‘proposedLoginName‘ and ‘mailAddress‘ values the user gives during registration. The Registration domain object gets populated with the values the user enters in the SubmitCommand.

Steps to Use the Commons Validator

Take the following steps to make the most of the Commons Validator component:

  1. Write or reuse a POJO validation class
    In order to use Commons Validator, the first step is to write classes that will perform the validations for a set of data. For this example, I wrote the class GenericBeanValidator to validate ‘proposedLoginName‘ and ‘mailAddress‘. The following is the GenericBeanValidator class structure:
    public class GenericBeanValidator {    public static boolean validateRequired(Object bean, Field field) {       String value = ValidatorUtils.getValueAsString(bean, field.getProperty());       return !GenericValidator.isBlankOrNull(value);    }    public static boolean validateEmail(Object bean, Field field) {       String value = ValidatorUtils.getValueAsString(bean, field.getProperty());       return GenericValidator.isEmail(value);    }}

    The validation class doesn’t adhere to any API, just a simple POJO class, which you can unit test easily. I use the ValidatorUtils and GenericValidator classes, which are part of Commons Validator, to achieve this goal. The getValueAsString method introspects the Registration bean to fetch the value for a property and returns a string. The GenericBeanValidator class acts like a wrapper around GenericValidator to validate a bean. The GenericValidator class contains many other utility methods to perform various validations. (Refer to the javadoc to make the best use of Commons Validator.)

  2. Define the mapping XML file
    The next step is to define a XML file that declares the validation classes (like the one written in the previous step) and wires them up to the beans, which need to be validated. The Validator engine will consume the XML file (more about this shortly). The registration.xml file for the example looks as follows:
                                    

    The validation classes need to be declared in the tag. Some of the key properties are logical name, class name, method name, method arguments, and message key, which will be used to fetch an error message if a validation fails. A couple of entries are defined for this example to validate the ‘proposedLoginName‘ and ‘mailAddress‘.

    The

    tag is used to map a definition to a Java Bean property. The tag in this example is used to fetch the externalized field name of a Java Bean property. This is useful when displaying a locale-specific displayable field name to the user. The displayable field names and error messages are externalized and available in the file applicationResource.properties. Any number of tags can appear in a definition.
  3. Initialize and execute the Validator
    When the Commons Validator engine is executed, it checks whether the XML file mapping has defined a validation for a property. If so, it invokes respective validation class methods by passing the necessary arguments. This process repeats for all the properties and the results accumulate along with the error messages. (You will see how to process the results later.)

    The following is a code snippet from the ValidatorEngine class, which the SubmitCommand uses:

            InputStream definitionStream = reg.getClass().getResourceAsStream(definitionXml);        ....        resources = new ValidatorResources(definitionStream);        ....        Validator validator = new Validator(resources, Registration.NAME);        validator.setParameter(Validator.BEAN_PARAM, reg);        ....        results = validator.validate();        ....        return parseResults(formName, reg, results, resources);

    The ValidationResources class represents the definitions in the XML file. You initialize this class by passing the definitionXml stream and passing the instance to the Validator, along with the name of the bean that needs to be validated. Additional parameters, which a validation class would require, can be passed to the Validator using the setParameter method. Remember, the validateXXXX methods in the GenericBeanValidator class had two arguments: java.lang.Object and org.apache.commons.validator.Field. When executed, the Validator will pass the instance of the bean for the first parameter and the respective field reference for the other.

    You might be wondering how the Validator would pass the reference of some other object (e.g., the HttpServletRequest object) to a validation method. The answer is by calling the setParameter method of the Validator with a fully qualified class name and the reference to the instance of the HttpServletRequest class. The validate method in the Validator can be called to initiate the validations.

  4. Process the results
    The Validator returns an instance of ValidatorResults upon execution. The instance holds all the information about the validations run. The visual structure of the results looks like this:
    [	[property1]		[action1]		[action2]	[property2]		[action1]]

    The results for every bean property are attached in the form of ValidatorAction instances. You begin to iterate over the properties and determine whether a validation succeeded or failed by calling the isValid method in the ValidatorResult class with the action name as a parameter. You’ll find the complete parsing logic in the parseResults method of the ValidatorEngine class.

  5. Alternative Uses
    The example has experimented with Commons Validator to validate user input backed by a Java Bean, but you can use it in numerous applications to reap the benefits of modular design, higher productivity, and easier maintenance. The following are some of the possible uses:
    • As a set of validations to apply in a purchase order submitted in XML format to the Web Service layer
    • Validating the state of a class in an application at any given point in time (Appropriate exceptions can be thrown if a class state is not as expected to fulfill a request.)
    • Monitoring an application along with JMX
    • In a rule engine implemented totally in Java (The validation classes would be treated as individual rules to act upon a domain object in a complex business application.)

    This framework also includes a few JavaScript functions to perform client-side validations in a Web application, such as email, URL, etc.

Collections

Commons Collections is a vast topic that could take up an entire article by itself. This article provides only a high-level understanding of the APIs and provides real-world examples for the most commonly used.

You may wonder why you need Commons Collections at all when the Java Collections Framework is available in the JDK. Well, Collections extends and enhances the Java Collections Framework’s classes and interfaces. In fact, I strongly feel that it also should be part of JDK itself.

The following are some of the features that I particularly like:

  • The bag interface
  • The fixed size, dual, and LRU maps
  • Iterator for an object array and map
  • MultiKey for a map
  • The numerous utility classes, which provide convenient methods for using the APIs
  • The decorators, which provide customized behavior for most of the classes

The Collections classes are organized in the following listed packages:

org.apache.commons.collectionsorg.apache.commons.collections.bagorg.apache.commons.collections.bidimaporg.apache.commons.collections.bufferorg.apache.commons.collections.collectionorg.apache.commons.collections.comparatorsorg.apache.commons.collections.functorsorg.apache.commons.collections.iteratorsorg.apache.commons.collections.keyvalueorg.apache.commons.collections.listorg.apache.commons.collections.maporg.apache.commons.collections.set

org.apache.commons.collections

The org.apache.commons.collections package contains interfaces, which are implemented in rest of the packages, and utility classes, which each act as a factory to instantiate a collection class or a decorated version of a collection class. Some of the interesting classes in this package are ArrayStack, BeanMap, ExtendedProperties, FastArrayList, FastHashMap, and FastTreeMap. The javadoc for these classes contains all the details, but Table 1 provides a quick note to explain each class’ real-world usage.

Collection Class Real-World Use
ArrayStack ArrayStack is a Stack implementation backed by an ArrayList for use in a single threaded environment. For instance, if you want to use Stack for some processing but only within a method, this implementation performs better than the Stack implemented using a Vector in JDK-1.4.2.
BeanMap Like the Swing GUI widget JButton, using this class, you can treat even a map as a Java Bean. A map can be dragged and dropped on the screen while designing a GUI to represent a data source or a set of configuration properties for the application.
ExtendedProperties This is my favorite class in this package. It is similar to java.util.Properties, which has a load method for loading configuration properties, but this implementation has the following benefits:
  • You can have multiple values for the same property key.
  • The value may be separated in different lines.
  • It offers convenient helper methods for fetching non-string values. For example, the getFloat method fetches a property of type float. You no longer need to write wrapper methods to parse the configuration property values.
  • FastArrayList, FastHashMap, FastTreeMap These classes can be used in a multi-threaded environment if the majority of the operations are read-only. These classes are backed by ArrayList, HashMap, and TreeMap, respectively.
    Table 1. Some Interesting Classes in the org.apache.commons.collections Package

    org.apache.commons.collections.bag

    The org.apache.commons.collections.bag class is very useful if your applications require you to add multiple copies of an object to a List. In these situations, I normally see developers add the objects to an ArrayList and iterate every time to determine the number of objects added for a given type. An online shopping cart is a good candidate for this requirement. The disadvantage of this approach is poor performance in terms memory and speed.

    A good design to address this requirement would be keeping one copy of the object and incrementing the count whenever a new entry of the same type is added. The HashBag and TreeBag classes in Commons Collections (backed by HashMap and TreeMap, respectively) address this requirement.

    The in.co.narayanan.commons.collections.bag package in the source code illustrates a real-world usage of a bag. The example processes the order for the software licenses of various operating systems and represents the ordered products in a bag.

    More specific versions or decorators are available for these classes as well. The javadoc offers a more detailed explanation.

    org.apache.commons.collections.bidimap

    Most Java developers have fetched a key by writing two HashMaps and passing a value as the key to the second map. Normally, you need to use this technique if you want to treat the name and value equally. Even the value could be a key in this case.

    The org.apache.commons.collections.bidimap example is a prototype adapter that integrates PeopleSoft and Siebel command-processing engines, assuming that every command in one has an equivalent in the other. You’ll find the relevant classes in the package in.co.narayanan.commons.collections.bidimap. You can start reading the code from the class SiebelPeopleSoftConnector, which acts as the adapter and holds the command mapping in a BidiMap. When a request arrives to process a Siebel command, the corresponding PeopleSoft command is retrieved from the BidiMap and passed to the PeopleSoft command engine. The reverse happens for PeopleSoft commands. The example contains only a skeleton of the application.

    The unmodifiable version of this class is handy if you want to design by contract, thereby prohibiting developers from altering the contents. This would greatly reduce the mistakes developers encounter while processing the contents.

    org.apache.commons.collections.buffer

    If you want to remove objects from a collection in a specific order, you can use implementations of the buffer interface. Some of its interesting classes are CircularFifoBuffer, PriorityBuffer, BoundedFifoBuffer, and BlockingBuffer. Decorated versions of each are available.

    You’ll find the buffer example in the package in.co.narayanan.commons.collections.buffer. It demonstrates the CircularFifoBuffer class, which you can think of as a moving window. The size of the collection is fixed, and the objects get removed in a first-in, first-out (FIFO) manner when it becomes full.

    The objective of the application is to report performance data to a remote server. Since the performance data is used only for monitoring, data loss is acceptable. A client application that wants to report performance data will need to instantiate class ReportPerformanceData and call method reportPerformance. The performance data will be added to the circular buffer.

    The class ReportTask removes the performance data object and sends it to the performance server. The concurrent utility class ThreadPoolExecutor in Java 1.5 is used to start the reporting task asynchronously, so that the data is reported as and when the buffer has some data to report.

    org.apache.commons.collections.collection

    The org.apache.commons.collections.collection package contains decorator classes, which implement the java.util.Collection interface directly. Therefore, any class that implements the Collection interface can make use of the decorators available here. Some of the commonly used classes are PredicatedCollection, CompositeCollection, SynchronizedCollection, TransformedCollection, TypedCollection, and UnmodifiableCollection. Table 2 provides a quick note on when to use each of these decorators.

    Decorator Class When to Use
    PredicatedCollection You want to restrict the addition of objects to a collection with a condition like “amount >= $15000”. To instantiate this class, you can define the condition as a separate object, which is called as a predicate and passed as an argument to the decorate factory method.
    CompositeCollection You want to create collections of collections and have a unified view while adding or removing objects.
    SynchronizedCollection You want to make an existing collection thread-safe.
    TransformedCollection You want to convert an object from one form to another (such as String to an Integer object) whenever adding to a collection.
    TypedCollection You want to restrict the object type being added to a collection. This is similar to Java 1.5 generics.
    UnmodifiableCollection You want to restrict modification to an existing collection reference.
    Table 2. Some Commonly Used Classes in the org.apache.commons.collections.collection Package

    org.apache.commons.collections.comparators

    This package contains various reusable classes, which you can use while sorting objects in a collection. The classes NullComparator and FixedOrderComparator are most interesting (see Table 3).

    Reusable Classes Function
    NullComparator Moves null entries towards the bottom while sorting entries in an array or a list
    FixedOrderComparator Restores the order in a collection to a predefined list
    Table 3. The NullComparator and FixedOrderComparator Classes

    org.apache.commons.collections.functors

    Un upcoming section discusses the org.apache.commons.collections.functors package in detail.

    org.apache.commons.collections.iterators

    Various classes in the org.apache.commons.collections.iterators package implement the java.util.Iterator interface. Some of the most useful are MapIterator, ArrayIterator, CollatingIterator, LoopingIterator, and IteratorUtils. You might want to go through the methods in the IteratorUtils class to make use of the classes in this package.

    org.apache.commons.collections.keyvalue

    The MultiKey class in the org.apache.commons.collections.keyvalue package is very useful. If you want to create domain objects in an application and store them in a map based on a composite primary key, you can create an instance of MultiKey by passing values of the primary key for that record. You can pass this instance to the map for storing the domain object.

    The other common use for this package is storing locale-specific entries in a map. In this case, the actual key and the locale name together will constitute the key.

    org.apache.commons.collections.list

    The TreeList, FixedSizeList, NodeCachingLinkedList, CursorableLinkedList, TransformedList, and PredicatedList classes in the org.apache.commons.collections.list package are interesting. The javadoc for these classes is self-explanatory.

    org.apache.commons.collections.map

    The CaseInsensitiveMap, CompositeMap, FixedSizeMap, Flat3Map, LazyMap, LinkedMap, LRUMap, MultiKeyMap, PredicatedMap, SingletonMap, and StaticBucketMap classes in the org.apache.commons.collections.map package are interesting. The javadoc for the classes are self-explanatory.

    org.apache.commons.collections.set

    The CompositeSet, ListOrderedSet, MapBackedSet, PredicatedSet, TransformedSet, TypedSet, and UnmodifiableSet classes in the org.apache.commons.collections.set package are interesting. The javadoc for the classes are self-explanatory.

    Chain

    The Gang of Four’s Chain of Responsibility (COR) behavioral design pattern is interesting and commonly used to model a set of operations. Each operation needs to be modeled as a command object and linked to others to form a chain. The command objects act upon some data and indicate whether the control should get passed to the next command in the chain. The benefit is that an operation can be added or removed easily without changing code. For successful execution, the arguments and the sub-commands passed from the command line while executing a command should be made available to the processing code.

    The Commons Chain component provides the interfaces and implementations necessary for using this pattern in an application. The API is neat and easy to understand. I’ve apply it to a real-world problem to explain its usage. Many developers have developed or at least used a CLI (Command Line Interface) application. The Commons Chain example is a CLI application for using the basic network protocols HTTP, FTP, and PING. (Find the source files in the package in.co.narayanan.commons.chain.) The following listing is a sampling of some of its commands:

    java CommandProcessor -user admin -password manager -ping {host}java CommandProcessor -user admin -password manager -ftp {host} -get {path_to_file}java CommandProcessor -user admin -password manager -http -get {path_to_file}

    The application uses the ?user and ?password arguments to validate a user against a local database and not for the network commands. The argument ?get is a subcommand to fetch a file for the given URL for both ?ftp and ?http master commands. To focus on demonstrating Commons Chain, the implementation contains only the skeleton code. Therefore, on executing the ?ping command, you print log messages to the console and don’t actually connect to the target. I leave it to you to complete this application. I recommend using the Commons Net API for this purpose.

    Using the COR pattern for this problem greatly simplified and improved the modularity of the design.

    CLI Context

    When a CLI command executes, the arguments and the subcommands need to be available for the processing code to successfully complete the operation. The CommandlineContext and CLICommand classes are the domain objects, which represent the commands, subcommands, and arguments.

    The CLICommand has a reference to itself. This is a Composite design pattern implementation to represent the subcommands, which enables nesting any number of commands. An instance of the CLICommand, along with user and password, will be contained in the CommandlineContext, thereby representing all the information of the executed CLI operation. The context will be passed to the commands in the chain during execution. It is up to each command in the chain to make use of the context information or pass the control to the next command.

    This example represents the CLI arguments as private variables and accesses them using getter methods in the context class. The alternative is to use the ContextBase implementation. It uses Java Bean introspection to fetch the attribute value and presents a Map view. Hence, dedicated getter methods like getUser and getPassword can be replaced with get(“user”) and get(“password”).

    Commands in the Chain

    After representing the context information necessary for a command, the next step is to model the commands, chains, and subchains. (Later, you will see how the Commons Chain API executes the commands and chains.) The class Ping is the command that gets executed for ?ping. This class uses the context passed in the execute method to check whether the command type is ?ping. If the command type is something else, the method returns false to notify the Chain framework that the control needs to be passed to the next command in the chain.

    The classes Ftp represents the master command ?ftp. Hence, it is modeled as a subclass of ChainBase in order to process the ftp subcommands ?get and ?ls. The execute method check the command type, if it is ?ftp, then the base class execute method is called for executing commands FtpGet and FtpLs in this chain. In this application, if a command contains a subcommand, such as ?http ?get, then it is modeled as a Chain to delegate the control further down to respective commands.

    The Chain

    The chains and commands identified for this application are visually presented here:

    Main ChainAuthenticator (Verifies user and password) --> Ping (Command) --> 
    Ftp (Sub-chain A) --> Default (Prints invalid command message)Sub-chain AFtpGet (Command) --> FtpLs (Command)

    The chain can be programmatically built at runtime using the ChainBase or CatalogBase class. The alternative is to specify the commands and chains in a XML file and use ConfigParser to build the chain. The catalog.xml file used for this application is presented here:

                                                                            

    Putting It All Together

    The following listing is the code to set up and run the Commons Chain framework:

            ConfigParser parser = new ConfigParser();        parser.parse(getClass().getResource("catalog.xml"));        Catalog catalog = CatalogFactoryBase.getInstance().getCatalog();        ....        Command command = catalog.getCommand("CommandProcessor");        command.execute(getPingCommand());        command.execute(getFtpGetCommand());        command.execute(getFtpLsCommand());        command.execute(getInvalidCommand());        command.execute(getInvalidCredentials());

    The catalog.xml file is parsed and the resultant Catalog reference is fetched from the CatalogFactoryBase. You have mocked the call to each of the CLI commands. You’ll find the complete code in the test case class TestChain. Ideally, a separate class will parse the command-line input to create context objects and pass them to the chain. You can use Commons CLI for this purpose.

    Functors

    The purpose of the Functors API is to model procedural program elements as objects. For example, you might have written code that evaluates the objects in a Vector or ArrayList for some condition and takes action based on its result. You might have written if-elseif-elseif-else or switch-case statements. Functors let you model the conditions like if-else or switch-case and the expressions within these conditions as separate objects. Why do you need this? Some of the benefits include the following:

    • The design becomes modular, and the features can be extended or modified easily. You can use strategy and command patterns together to switch algorithms in an operation for a condition.
    • It simplifies writing unit test cases.
    • It allows dynamic loading of the operation for a condition using reflection.

    Technically, most of the program elements (if, while, for, switch, etc.) can be modeled using functors. The common use of this concept is for series of if-else statements, switch-case statements, and operations to perform on a collection.

    Important interfaces in this API are Predicate and Closure. A Predicate is used to represent a condition. If the result is true, then the Closure’s execute method will be called.

    The Functors example is a simple script-processing engine that processes database commands. It uses functors to model the switch-case decision tree, which decides which command class should be invoked for a script command. You’ll find the complete source code in the in.co.narayanan.commons.collections.functors package. The following listing provides the command syntax:

    add , delete , , modify , , , 

    The script engine will need to execute a SQL insert to the database when it encounters an add script command. Similarly, other commands have to be processed as well. The class ScriptCommand is the domain object, which represents a script command and its arguments. The classes AddTask, DeleteTask, and ModifyTask contain the logic to execute for a script command. To understand the traditional way for modeling this engine, review the following code snippet from the class ProcessCommand1:

        public void process(ScriptCommand command) {        switch(command.getType()) {            case ADD: {                executeAdd(command);            } break;            case MODIFY: {                executeModify(command);            } break;            case DELETE: {                executeDelete(command);            } break;        }    }

    It checks the script command type in a switch-case block and executes the appropriate command.

    The following listing from ProcessCommand2 illustrates the same behavior achieved using functors:

        public void start() {        Map predicatesAndClosures = new Flat3Map();        predicatesAndClosures.put(new AddPredicate(), new AddClosure());        predicatesAndClosures.put(new ModifyPredicate(), new ModifyClosure());        predicatesAndClosures.put(new DeletePredicate(), new DeleteClosure());        Closure switchClosure = ClosureUtils.switchClosure(predicatesAndClosures);        CollectionUtils.forAllDo(commands, switchClosure);    }    private static class AddPredicate implements Predicate {        public boolean evaluate(Object object) {            ScriptCommand command = (ScriptCommand)object;            return command.getType() == CommandType.ADD ? true : false;        }    }    private static class AddClosure implements Closure {        public void execute(Object input) {            ScriptCommand command = (ScriptCommand)input;            AddTask add = new AddTask();            add.add(command.getTableName(), command.getArgs());        }    }

    The AddPredicate evaluates the command type, and the AddClosure contains the logic to perform the add script command. The predicates and closures are mapped and passed to the switchClosure method in the ClosureUtils utility class. The SwitchClosure reference returned evaluates the predicates and calls mapped to closure if the result is true. This is repeated for each predicate in the map until one returns true.

    This example shows that closures can be used together to achieve program flow. It uses AddClosure, which was written, and SwitchClosure in the Commons Collections API together. The SwitchClosure reference can be used with IfClosure, for instance.

    A very common use of functors in a business application is applying a set of business rules to a collection of domain object instances and taking action with respect to the rule results. The rules need to be modeled as predicates and the actions need to be modeled as closures. You can build a complete rule engine using the Python scripting language if you integrate it to Jython. In this case, the Python scripts need to be used for writing the predicates and closures.

    Lang

    This Lang API is an extension to the java.lang package. I hope Commons Lang becomes part of the JDK in the future. This package contains many utility methods that you can use in Java projects. (A comprehensive user guide is available at the Jakarta Web site, and the javadoc contains simple usage of most of the classes.) This article explains only the classes that I like the most and strongly feel that any developer would be interested to try. The source files for examples are provided in the in.co.narayanan.commons.lang package.

    The StringUtils, WordUtils, StringEscapeUtils, and RandomStringUtils classes provide useful string-manipulation methods. The following listings show the usage of some of these methods, which frequently are required.

    The following abbreviated method displays parts of the message if the display area in the GUI is limited (a JTable cell, for instance):

            String message = "Please check the logs for an error.";        message = StringUtils.abbreviate(message, 25);

    The following method is very useful in desktop applications developed with Java. For instance, a Java Swing application that requires a feature to compose and send emails:

            String message = "jakarta commons";        message = StringUtils.capitalize(message);

    The following methods from the WordUtils classes are variants in capitalizing a string:

            String message = "jakarta commons";        message = WordUtils.capitalize(message);

            String message = "jakarta COMMONS";        message = WordUtils.capitalizeFully(message);

    The javadoc contains explains the usage further.

    This method is useful for positioning a message by filling lead and trail spaces:

            String message = "java";        message = StringUtils.center(message, 10);

    You no longer need to write code to tokenize a string for processing. The split method does it for you by returning a String array. You can create a new string from a String array using the join method:

            String message = "hello how are you";        String messageTokens[] = StringUtils.split(message, ' ');        String newMessage = StringUtils.join(messageTokens, '$');

    Making a password in a String becomes easy with the overlay method. The replace method is intelligent enough to search for a word and replace it. You don’t have to worry about character positions:

            String message = "This is a demo for replace and overlay feature";        message = StringUtils.replace(message, "demo", "illustration");        message = "Your password is: somepassword";        message = StringUtils.overlay(message, "*****", 18, message.length());

    Methods are available in the StringEscapeUtils class to escape and un-escape HTML, Java strings, JavaScript strings, SQL, and XML:

            String html = "

    This will be displayed in the HTML page.
    Hence the tags will be escaped.

    "; String escapedHtml = StringEscapeUtils.escapeHtml(html);

    This method can be used to generate random passwords:

            String randomPassword = RandomStringUtils.randomAlphanumeric(8);        System.out.println("Random Password:" + randomPassword);

    A brief note on each package is given below:

    org.apache.commons.lang

    The ArrayUtils, BooleanUtils, CharRange, CharSet, CharUtils, SystemUtils, and Validate classes are interesting and worth investigating in the javadoc.

    org.apache.commons.lang.builder

    The CompareToBuilder, EqualsBuilder, HashCodeBuilder, and ToStringBuilder classes assist in implementing the compareTo, equals, hashCode, and toString methods, respectively. Almost all Java projects require these classes.

    org.apache.commons.lang.enums

    Enum support is available in Java 1.5. Hence, this package can be useful for pre-JDK 1.5 projects. The package’s javadoc contains an example that illustrates its use.

    org.apache.commons.lang.exception

    The NestableException class provides support to link the cause for an exception. Why is this useful? The stack trace of all exceptions can be handy for quickly determining the root cause of an error. This can be used for pre-JDK1.4 projects. Since 1.4, Java has included support for nested exceptions.

    org.apache.commons.lang.math

    The IntRange, Fraction, NumberUtils, and RandomUtils classes are interesting and the worth investigating in the javadoc.

    org.apache.commons.lang.mutable

    The wrapper for primitive types in the java.lang package is immutable. This package contains wrapper classes, which are mutable. The javadoc provides further explanation.

    org.apache.commons.lang.time

    Some of this package’s useful classes are DateUtils, DataFormatUtils, FastDateFormat, and StopWatch. The javadoc provides further explanation.

    So What Have You Learned?

    Now that you’ve completed this first installment of the Jakarta Commons series, you should have learned the following:

    • The rich features provided by various Commons components
    • Where you can use a particular component or method from a utility class in a real-world Java project
    • The design patterns various APIs use
    • A high-level understanding of the packages and classes in various APIs

    Now, during Java application design or development, you’ll be in a position to pick a useful class and use it appropriately. Parts II and III of this series will discuss more interesting components. By the end, you too will be convinced that most of the classes in the Jakarta Commons components should be part of JDK.

    devxblackblue

    About Our Editorial Process

    At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

    See our full editorial policy.

    About Our Journalist