1.4. Automating the Generation of toString( ) Content

Problem

You want to automate the creation of toString( ) methods.

Solution

Use the Commons Lang ReflectionToStringBuilder or ToStringBuilder and ToStringBuilder to create toString() methods. The following code is an example of a toString( ) method, which uses a reflection builder:

import org.apache.commons.lang.builder.ToStringBuilder;

public void toString( ) {
    ReflectionToStringBuilder.toString( this );
}

Discussion

Assume that you have an object named PoliticalCandidate—a bean that represents some information about a presidential candidate. This bean has a set of properties: firstName, lastName, dateOfBirth, moneyRaised, and homeState. Example 1-1 shows the PoliticalCandidate class using a ReflectionToStringBuilder; the getter and setter methods have been omitted for brevity.

Example 1-1. The PoliticalCandidate class using ReflectionToStringBuilder

import java.math.*;
import java.util.*;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

public class PoliticalCandidate {

    private String lastName;
    private String firstName;
    private Date dateOfBirth;
    private BigDecimal moneyRaised;
    private State homeState;

    // get/set methods are omitted for brevity...

    public void toString( ) {
        ReflectionToStringBuilder.toString( this );
    }
}

The process of keeping the contents of a toString() method synchronized with a changing object model becomes a chore (usually a forgotten one). Commons Lang includes a fairly simple utility designed to automate this chore using reflection. The ToStringBuilder class and its extension, ReflectionToStringBuilder , can condense a large toString( ) method body into one line of code. Most importantly, the ReflectionToStringBuilder reflects any future changes that are made to the object model. The following code demonstrates the output of a string built via reflection:

// Create a State
State va = new State( "VA", "Virginia");

// Create a Birth Date
Calendar calendar = new GregorianCalendar( );
calendar.set( Calendar.YEAR, 1743 );
calendar.set( Calendar.MONTH, Calendar.APRIL );
calendar.set( Calendar.DAY_OF_MONTH, 13 );
Date dob = calendar.getTime( );

BigDecimal moneyRaised = new BigDecimal( 293829292.93 );        

// Create a Political Candidate
PoliticalCandidate candidate = 
    new PoliticalCandidate( "Jefferson", "Thomas", dob, moneyRaised, va );
        
System.out.println( candidate );

Assume that the State object is another bean using the same ReflectionToStringBuilder. The code above sets the properties of a bean and produces the following output:

com.discursive.jccook.lang.builders.PoliticalCandidate@187aeca
    [lastName=Jefferson,\firstName=Thomas,
     dateOfBirth=Sat Apr 13 22:38:42 CST 1743,
     moneyRaised=\293829292.930000007152557373046875,
     state=\com.discursive.jccook.lang.builders.State@87816d
         [abbreviation=VA,name=Virginia]]

Tip

As in other cases in this book, I’ve applied a minimal amount of formatting to the output so that it fits on the printed page. Your results will be the same in terms of content but will be all on one long line.

This is not the most readable piece of information in the world, but it was automatically generated. Keeping a toString( ) method up-to-date in an object model that contains one hundred entities is next to impossible under the constraints of a deadline and a budget. If your objects have meaningful toString( ) methods, it will be much easier to diagnose problems in your application. If you use the ReflectionToStringBuilder, you are assured that the message printed out will be accurate; the alternative is to have a message that may or may not be relevant—trusting developers to keep toString( ) methods updated manually.

Warning

This utility uses the class AccessibleObject in the J2SE reflection package to bypass access modifiers and access private member variables of an object directly. If your system is running under a restrictive SecurityManager, you may need to alter your configuration to allow Commons Lang to bypass these security restrictions. Only use this reflection builder if you are certain that your code will run in an environment without a restrictive security policy. I use this utility in a system that runs on a few servers in a known location, but if I were writing a reusable library, a reflection builder would not be feasible; if someone were to use my library in an environment with a different security policy, calling a toString( ) may cause problems. The relevant permission is the suppressAccessChecks permission target of the java.lang.reflect.ReflectPermission class.

Get Jakarta Commons Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.