Over a million developers have joined DZone.

Refactor-Safe ToStringBuilder

· Java Zone

What every Java engineer should know about microservices: Reactive Microservices Architecture. Brought to you in partnership with Lightbend.

We at GridGain recently were faced with a problem - how to make our toString() methods refactor-safe? Up until recently we were using simple toString() plugins for IDEA and Eclipse (Jutils) which generated toString() method automatically based on class fields. Then developer would have to tweak the generated code to remove fields that should not be included.

However, faced with numerous support questions, we noticed that sometimes during refactoring a developer would forget to add a new field to existing toString() method or print out too much and clutter up the log. Surprisingly, there is no open source library that supports this basic functionality (ToStringBuilder from Apache is not even close), so we had to implement our own. So, to summarize, the functionality we needed is this:

  • Make sure that new fields are automatically included.
  • Make sure that certain classes, like Object, Collection, Array are automatically excluded.
  • Provide class-level overrides of default rules, which will include auto-excluded fields and vice versa.
  • Provide support for custom ordering of fields in toString() output.

Here is the design we came out with:

@GridToStringInclude Annotation This annotation can be attached to any field in the class to make sure that it is automatically included even if it is excluded by default.

@ToStringExclude Annotation This annotation can be attached to any field in the class to make sure that it is automatically excluded even if it is included by default.

@ToStringOrder(int) Annotation This annotation provides custom ordering of class fields. Fields with smaller order value will come before in toString() output. By default the order is the same as the order of field declarations in the class.

ToStringBuilder Class This class is responsible for reflectively parsing all fields in class hierarchy, caching all annotations for performance reasons, and properly outputting toString() content.

So, here is an example of a class that uses this simple framework:

public class MySimpleClass {
/**
* This field would be included by
* default, but is excluded due to
* @ToStringExclude annotation.
*/
@ToStringExclude
private int intField = 1;

/**
* This field will be included
* first for toString() purposes.
*/
private String strField = "TestString";

/**
* This array field would be excluded
* by default, but is included due to
* @ToStringInclude annotation.
*/
@ToStringInclude
private int[] intArr = new int[] { 1, 2, 3 };

/**
* This field is excluded by default.
*/
private Object obj = new Object();

/**
* Generic toString() implementation.
*/
@Override
public String toString() {
return ToStringBuilder.toString(MySimpleClass.class, this);
}
}

The toString() output of the class above will look as follows:

MySimpleClass [strField=TestString, intArr={1,2,3}]

The complete source code is available in our public WebSVN . When clicking on this link you will be prompted with login popup. Just enter "guest" for username and leave the password blank. The source code is in org.gridgain.grid.utils.toString package.

Enjoy!

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O’Reilly book. Brought to you in partnership with Lightbend.

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}