The Artima Developer Community
Sponsored Link

Code by Any Other Name
Announcing Pojomatic 2.0
by Ian Robertson
June 30, 2014
Summary
Pojomatic 2.0 has been released, and uses InvokeDynamic to give performance nearing that of hand-rolled code.

Advertisement

Announcing Pojomatic 1.0

Version 2.0 of Pojomatic has been released. Pojomatic provides an easy way to implement the equals(Object), hashCode() and toString() methods inherited from java.lang.Object.

This release targets Java 7 or higher. The reason for this is to take advantage of the new InvokeDynamic instruction introduced in Java 7. While Pojomatic 1.0 used reflection to do it's work, this new version generates byte code using ASM, and uses InvokeDynamic to be able to access potentially private members of pojomated classes. The result is that the performance of equals and hashCode is now close to that of what would be seen with hand-rolled code. (To learn more about how this is done, come see my JavaOne talk this year).

Starting in Java 7, reflection no longer will necessarily return a class's elements in any particular order. Consequently, this release also uses ASM to read in the class file for a pojomated class, in order to determine the original order of fields and methods on the class.

Overview of Pojomatic

For those not familiar with Pojomatic, the typical work needed for most classes is:

import org.pojomatic.Pojomatic;
import org.pojomatic.annotations.AutoProperty;

@AutoProperty // tells Pojomatic to use all non-static fields.
public class Pojo {
  // Fields, getters and setters...

  @Override public boolean equals(Object o) { return Pojomatic.equals(this, o); }
  @Override public int hashCode() { return Pojomatic.hashCode(this); }
  @Override public String toString() { return Pojomatic.toString(this); }
}

While this is adequate more most cases, there are numerous ways to customize how Pojomatic will build up the implementations of the equals, toString and hashCode methods. The @AutoProperty annotation can instruct Pojomatic to use fields or getters to accesses properties. Alternatively, one can annotate individual fields and/or accessor methods with the @Property annotation to include them explicitely, or to exclude certain properties if @AutoProperty is being used. For any property, a @PojomaticPolicy can be set to indicate which methods the property should be included in. By default, a property is used for each of the equals, hashCode and toString methods, but any combination is possible, subject to the restriction that if a property is used for hashCode, then it must be used for equals as well.

Proper implementation of equals for class hierarchies

As discussed in How to Write an Equality Method in Java, challenges arise in satisfying the contract for equals when class hierarchies come into play. The solution suggested in that article is to introduce an additional method, canEqual, which the implementation of equals will use to ensure that instances of a parent class do not accidentally declare themselves to be equal to an instance of a subclass which has redefined equals. If all the classes in a hierarchy use Pojomatic, this step is not necessary; Pojomatic keeps track of whether instances of two related classes can be equal to each other or not via the areCompatibleForEquals method. Two classes are compatible for equality if they each have the same set of properties designated for use with the equals method. If a subclass has a need to implement the equals method without using Pojomatic, it can be annotated with @OverridesEquals to indicate that it is not compatible for equality with it's parent class.

Comparing two Pojomated instances

A common use of the equals method is to facilitate the use of the assertEquals methods of JUnit or TestNG. When assertEquals fails, the exception method includes the toString representation of each instance. One pain point which no doubt will be familiar to many is that of trying to determine why two instances are not equal when they have a large number of properties. Often, the only option is to copy the failure message into an editor which allows comparing the toString representations to look for differences. Pojomatic helps address this by adding method, Pojomatic.diff which can reveal the differences between two instances of a Pojomated class. The PojomaticTestUtils library leverages this capability to provide an assertEqualsWithDiff method which will call out the differences between two instances in the failure messaged in the event that they are not equal.

Getting Pojomatic

Pojomatic is available on the central maven repository; if you use maven, it is just a dependency away:

    <dependency>
      <groupId>org.pojomatic</groupId>
      <artifactId>pojomatic</artifactId>
      <version>1.0</version>
    </dependency>
Others can download Pojomatic from the central maven repository.

Talk Back!

Have an opinion? Be the first to post a comment about this weblog entry.

RSS Feed

If you'd like to be notified whenever Ian Robertson adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Ian Robertson is an application architect at Verisk Health. He is interested in finding concise means of expression in Java without sacrificing type safety. He contributes to various open source projects, including jamon and pojomatic.

This weblog entry is Copyright © 2014 Ian Robertson. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use