0

We extend JAXBEqualsStrategy via pom:

<xjcArg>-Xequals-equalsStrategyClass=com.acme.foo.CustomEqualsStrategy</xjcArg>

The CustomEqualsStrategy extends JAXBEqualsStrategy. After running MAVEN clean install generate-source in Eclipse (Keplar) our model classes have equals method like this:

    public boolean equals(Object object) {
      final EqualsStrategy strategy = new CustomEqualsStrategy();
      return equals(null, null, object, strategy);
    }

Whereas if we do not extend JAXBEqualsStrategy, our model classes have equals method like this:

    public boolean equals(Object object) {
      final EqualsStrategy strategy = JAXBEqualsStrategy.INSTANCE;
      return equals(null, null, object, strategy);
}

JAXBEqualsStrategy has

    public static EqualsStrategy INSTANCE = new JAXBEqualsStrategy();

We expected to get

    final EqualsStrategy strategy = CustomEqualsStrategy.INSTANCE;

in the generated equals method and are struggling to accomplish it.

2 Answers2

0

You do not want to use CustomEqualsStrategy.INSTANCE. Using new CustomEqualsStrategy() is correct and should be preferred unless you have very good reasons for doing otherwise.

Since CustomEqualsStrategy extends JAXBEqualsStrategy, that means that unless you define your own INSTANCE field inside CustomEqualsStrategy, CustomEqualsStrategy.INSTANCE is the same as JAXBEqualsStrategy.INSTANCE, which means that you would be using an instance of JAXBEqualsStrategy after all.

Plus, using an INSTANCE field like that effectively signals that your class is meant to be used as a singleton, and thus has to be stateless. Most classes are not stateless, and even for classes that are, many such classes don't need to be used in a singleton style.

In short, really just stick with new CustomEqualsStrategy(). The code will have fewer surprises and you'll be happier for it. (Also, from reading the code for JAXBEqualsStrategy, perhaps you should be extending DefaultEqualsStrategy instead.)

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Thank you very much for the reply. We took our cue from Apache's ElementAwareEqualsStrategy which extends JAXBEqualsStrategy. The concern is that calling equals will (needlessly?) instantiate a new CustomEqualsStrategy. – eisjake Jul 27 '14 at 13:16
  • I don't see no problems making strategy classes completely stateless, reenterable and singletons. From the other hand there's a lot of cases where equals and hashCode must be very fast so avoiding creating new instances of strategies might be a very good idea. – lexicore Aug 01 '14 at 11:26
0

Disclaimer: Plugin author here.

Actually, you can also get .INSTANCE or .getInstance()-calls generated as well. Please see this code:

https://svn.java.net/svn/jaxb2-commons~svn/basics/trunk/basic/src/main/java/org/jvnet/jaxb2_commons/plugin/util/StrategyClassUtils.java

So:

  • If the class of your equals strategy is known to the plugin in the runtime AND
  • Your class has a public static getInstance() method of the correct type OR
  • Your class has a public static field INSTANCE of the correct type

Then the plugin will use YourStrategy.getInstance() or YourStrategy.INSTANCE instead of new YourStrategy().

I guess you already have an INSTANCE method. Please try to include the JAR with your strategy into the XJC classpath (so that plugin could resolve your strategy class during the compile time).

Please also feel free to file an issue to support syntax like -Xequals-equalsStrategyInstanceField=com.acme.foo.CustomEqualsStrategy.INSTANCE or InstanceMethod accordingly.

lexicore
  • 42,748
  • 17
  • 132
  • 221