groovy,equality , In Groovy, why does the behaviour of '==' change for interfaces extending Comparable?

In Groovy, why does the behaviour of '==' change for interfaces extending Comparable?


Tag: groovy,equality

I'm trying to develop a project in Groovy and I've found some of my tests failing in an odd way: I have an interface Version extends Comparable<Version> with two concrete subclasses. Both override equals(Object) and compareTo(Version) - however, if I try to compare two instances of Version that are of different concrete types using ==, the equality check fails even though explicit equals and compareTo checks pass.

If I remove the extends Comparable<Version> part of Version, I get the expected behaviour - == gives the same result as equals would.

I've read elsewhere that Groovy delegates == to equals() unless the class implements Comparable, in which case it delegates to compareTo. However, I'm finding cases where both declare two instances of Version to be equal and yet the == checks fail.

I've created an SSCCE that demonstrates this behaviour here.

The full code is also provided below:

// Interface extending Comparable
interface Super extends Comparable<Super> {
    int getValue()

class SubA implements Super {
    int getValue() { 1 }
    int compareTo(Super that) { this.value <=> that.value }
    boolean equals(Object o) {
        if (o == null) return false
        if (!(o instanceof Super)) return false
        this.value == o.value

class SubB implements Super {
    int getValue() { 1 }
    int compareTo(Super that) { this.value <=> that.value }
    boolean equals(Object o) {
        if (o == null) return false
        if (!(o instanceof Super)) return false
        this.value == o.value

// Interface not extending Comparable
interface AnotherSuper {
    int getValue()

class AnotherSubA implements AnotherSuper {
    int getValue() { 1 }
    boolean equals(Object o) {
        if (o == null) return false
        if (!(o instanceof AnotherSuper)) return false
        this.value == o.value

class AnotherSubB implements AnotherSuper {
    int getValue() { 1 }
    boolean equals(Object o) {
        if (o == null) return false
        if (!(o instanceof AnotherSuper)) return false
        this.value == o.value

// Check with comparable versions
def a = new SubA()
def b = new SubB()

println "Comparable versions equality check: ${a == b}"
println "Explicit comparable equals check: ${a.equals(b)}"
println "Explicit comparable compareTo check: ${a.compareTo(b)}"

// Check with non-comparable versions
def anotherA = new AnotherSubA()
def anotherB = new AnotherSubB()

println "Non-comparable versions equality check: ${anotherA == anotherB}"
println "Explicit non-comparable equals check: ${anotherA.equals(anotherB)}"

What I'm getting back is:

Comparable versions equality check: false
Explicit comparable equals check: true
Explicit comparable compareTo check: 0
Non-comparable versions equality check: true
Explicit non-comparable equals check: true

I think I understand why this happens now, thanks to the JIRA discussion that Poundex linked to below.

From Groovy's DefaultTypeTransformation class, which is used to handle equality/comparison checks, I assume that the compareEqual method is first called when a statement of the form x == y is being evaluated:

public static boolean compareEqual(Object left, Object right) {
    if (left == right) return true;
    if (left == null || right == null) return false;
    if (left instanceof Comparable) {
        return compareToWithEqualityCheck(left, right, true) == 0;
    // handle arrays on both sides as special case for efficiency
    Class leftClass = left.getClass();
    Class rightClass = right.getClass();
    if (leftClass.isArray() && rightClass.isArray()) {
        return compareArrayEqual(left, right);
    if (leftClass.isArray() && leftClass.getComponentType().isPrimitive()) {
        left = primitiveArrayToList(left);
    if (rightClass.isArray() && rightClass.getComponentType().isPrimitive()) {
        right = primitiveArrayToList(right);
    if (left instanceof Object[] && right instanceof List) {
        return DefaultGroovyMethods.equals((Object[]) left, (List) right);
    if (left instanceof List && right instanceof Object[]) {
        return DefaultGroovyMethods.equals((List) left, (Object[]) right);
    if (left instanceof List && right instanceof List) {
        return DefaultGroovyMethods.equals((List) left, (List) right);
    if (left instanceof Map.Entry && right instanceof Map.Entry) {
        Object k1 = ((Map.Entry)left).getKey();
        Object k2 = ((Map.Entry)right).getKey();
        if (k1 == k2 || (k1 != null && k1.equals(k2))) {
            Object v1 = ((Map.Entry)left).getValue();
            Object v2 = ((Map.Entry)right).getValue();
            if (v1 == v2 || (v1 != null && DefaultTypeTransformation.compareEqual(v1, v2)))
                return true;
        return false;
    return ((Boolean) InvokerHelper.invokeMethod(left, "equals", right)).booleanValue();

Notice that if the LHS of the expression is an instance of Comparable, as it is in the example I provide, the comparison is delegated to compareToWithEqualityCheck:

private static int compareToWithEqualityCheck(Object left, Object right, boolean equalityCheckOnly) {
    if (left == right) {
        return 0;
    if (left == null) {
        return -1;
    else if (right == null) {
        return 1;
    if (left instanceof Comparable) {
        if (left instanceof Number) {
            if (right instanceof Character || right instanceof Number) {
                return DefaultGroovyMethods.compareTo((Number) left, castToNumber(right));
            if (isValidCharacterString(right)) {
                return DefaultGroovyMethods.compareTo((Number) left, ShortTypeHandling.castToChar(right));
        else if (left instanceof Character) {
            if (isValidCharacterString(right)) {
                return DefaultGroovyMethods.compareTo((Character)left, ShortTypeHandling.castToChar(right));
            if (right instanceof Number) {
                return DefaultGroovyMethods.compareTo((Character)left,(Number)right);
        else if (right instanceof Number) {
            if (isValidCharacterString(left)) {
                return DefaultGroovyMethods.compareTo(ShortTypeHandling.castToChar(left),(Number) right);
        else if (left instanceof String && right instanceof Character) {
            return ((String) left).compareTo(right.toString());
        else if (left instanceof String && right instanceof GString) {
            return ((String) left).compareTo(right.toString());
        if (!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
                || (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
                || (left instanceof GString && right instanceof String)) {
            Comparable comparable = (Comparable) left;
            return comparable.compareTo(right);

    if (equalityCheckOnly) {
        return -1; // anything other than 0
    throw new GroovyRuntimeException(
            MessageFormat.format("Cannot compare {0} with value ''{1}'' and {2} with value ''{3}''",

Down near the bottom, the method has a block that delegates the comparison to the compareTo method, but only if certain conditions are satisfied. In the example I provide, none of these conditions are satisfied, including the isAssignableFrom check, since the example classes I provide (and the code in my project that's giving me the problem) are siblings, and therefore not assignable to one another.

I suppose I understand why the checks are failing now, but I'm still puzzled over the following things:

  1. How do I get around this?
  2. What's the rationale behind this? Is this a bug or a design feature? Is there any reason why two subclasses of a common super class should not be comparable with one another?


The answer to why Comparable is used for == if existing is easy. It is because of BigDecimal. If you make a BigDecimal out of "1.0" and "1.00" (use Strings not doubles!) you get two BigDecimal that are not equal according to equals, because they don't have the same scale. Value-wise they are equal though, which is why compareTo will see them as equal.

Then of course there is also GROOVY-4046, which shows a case in which just directly calling compareTo will lead to a ClassCastException. Since this exception is unexpected here we decided to add an check for assignability.

To get around this you can use <=> instead which you already found. Yes, they still go through DefaultTypeTransformation so you can compare for example an int and an long. If you don't want that either, then directly calling compareTo is the way to go. If I misunderstood you and you want to actually have equals, well, then you should call equals of course instead.


Groovy: run SQL SELECT LIKE from file with params

The groovy code is import groovy.sql.* dbUrl = 'jdbc:sqlserver://server' dbUser = 'username' dbPassword = 'password' dbDriver = '' sql = Sql.newInstance(dbUrl, dbUser, dbPassword, dbDriver) def sqlfromfile = new SqlFromFile() sqlfromfile.sql_filename='select_query.sql' try{ def result = sql.rows(sqlfromfile.result,[id:'01']) println result }catch(e){ println e } class SqlFromFile { def sql_filename def read(){ result=...

Spock's @Narrative and @Title annotations

Spock provides @Narrative and @Title annotations that you can use to provide a class-level description of your test, e.g. @Narrative('description of spec') @Title('title of spec') class ExampleSpec extends Specification { // tests omitted } What is the difference between these two? In other words, why do we need both of...

Get just content of soap response in Groovy

I have following soap response: <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="" xmlns:xsi="" xmlns:xsd=""> <soap:Body> <GetHTMLResponse xmlns="http://www.webserviceX.NET"> <GetHTMLResult> TEST </GetHTMLResult> </GetHTMLResponse> </soap:Body> </soap:Envelope> Now I want a method which deliverys me this xml: <root> <GetHTMLResponse...

Parse RSS with groovy

I am trying to parse RSS feeds with groovy. I just wanted to extract the title and description tags' value. I used following code snippet to achieve this: rss = new XmlSlurper().parse(url) { titleList.add(it.title) descriptionList.add(it.description) } After this, I am accessing these values in my JSP page. What is...

list of test step results in groovy script

I'm trying to figure out a way to get a list of (names) of just the failed test steps, currently the below code is giving me all the names def TestCase = testRunner.getTestCase() def StepList = TestCase.getTestStepList() StepList.each { ( } Now I'm not sure how to move on...

null object error when calling code from script assertion - soapui

In a soapui groovy script test step I've this. context.setProperty("searchChange", new searchChange()); class searchChange{ def testRunner def searchChange(testRunner){ this.testRunner=testRunner } def search(a,b){ def search_TestCase = testRunner.testCase.testSuite.getTestCaseByName("Search") search_TestCase.setPropertyValue("Search_cID", a) search_TestCase.setPropertyValue("Search_sID", b), false) } } and in an assertion script in a different test suite I am...

groovy/XML: Replace a node by another one

I try to replace an XML node by another one by using XmlSlurper (or XmlParser). The original XML: <myXml> ... <myNode> <Name>name1</Name> <Name>name2</Name> <Name>name3</Name> </myNode> ... </myXml> The list that contains the items to build my new node def namelist = ['name4','name5','name6','name7'] What I want to have <myXml> ... <myNode>...

Class fields as method parameters

My method needs to be strictly typed. If possible, I wanted to save some line of codes, setting the model properties from the parameter input by putting the model properties setter directly at the function definition. The current working code: class Connector { static def entityQuery( String httpMethod, String typeName,...

set an annotation attribute from an environment variable?

I'm trying to set an annotation value from an environment variable: @Configuration @ComponentScan @EnableAutoConfiguration @EnableScheduling class Application { @Scheduled(cron = "${DB_CRON}") def void schedule() { ... } public static void main(String... args) {, args) } ... } However, I get the following compile time error: Attribute 'cron' should have...

Model to LazyMap

How do I convert/deserialize these models public class AccessCredentials { String userName = '' String password = '' LoginOptions loginOptions = new LoginOptions() } public class LoginOptions { String partnerId = '' String applicationId = '' } into a LazyMap like : [ userName : userName, password : password, loginOptions...

To check objects inside std::array has identical member data

Cards.h class Card { public: // Card suits struct Suit { // Suits in order enum Enum { Clubs, Diamonds, Hearts, Spades, }; }; // Card rank struct Rank { // Ranks with aces low enum Enum { Ace, Two, King, .... ... }; }; // constructors //get & set...

How to use multiple classes in multiple files in scripts?

I need to make a standalone Groovy script that does not require compilation and runs without Groovy installed. It works well, but it fails to recognize any other script than the main script. My folder structure is the following: libs\ groovy-all-2.4.3.jar ivy-2.4.0.jar src\ makeRelease.groovy ReleaseHelper.groovy I am launching the script...

Groovy TimeDuration Argument Types

I'm quite new to groovy (and haven't any experience with Java) - but I'm running into a problem that doesn't make sense to me. My guess is that its my misunderstanding of how objects and classes work in these languages. My question is probably very basic - any help is...

create email list of all users

On occasion I need to email all Jenkins users, for example warning them Jenkins will be offline for maintenance. The script below gives me email addresses for all people that Jenkins knows about, but it includes people that don’t have accounts, these are people that have committed changes that triggered...

Elasticsearch : _score always 0 in Groovy script

I have this kind of Groovy script: def multiplier = doc['data'].value if (multiplier <= 0) { multiplier = 1 } multiplier * _score I use it as a script_score, and my score is always 0. It seems like _score is always 0. With a mvel script, it works. mvel script...

sonar maven analysis only picks .java file

I am trying to run a sonar maven analysis on my multilanguage project which contains many languages like *.java, *.groovy, *.js etc. I have installed all the languages plugin in my sonar and configured my pom sonar.sources parameter as src/main,src/test but still it picks up only java files. In the...

Restrict allowed httpMethods using enum

I am creating connectors for REST API methods. Some methods has the same method name but performs different HTTP methods. For example, createEntity( HttpMethod httpMethod, CreateEntity model ) can perform POST and GET only. What I want is to have an error when httpMethod is supplied with PUT or DELETE....

Confused about the invokeMethod method in the Groovy MOP

First look at the following Groovy code: class Car { def check() { System.out.println "check called..." } def start() { System.out.println "start called..." } } Car.metaClass.invokeMethod = { String name, args -> System.out.print("Call to $name intercepted... ") if (name != 'check') { System.out.print("running filter... ") Car.metaClass.getMetaMethod('check').invoke(delegate, null) } def validMethod...

Why does the Java equals(Object O) method not have a variant which can take a specific object type (e.g. String, Integer, etc) as input?

I come across problems where I need to compare two strings (or any other object ) for equality/non-equality using Java language. There are two methods on String Object very useful for this purpose viz. compareTo(Object O), which returns a integer result of comparison while other equals(Object o), which returns a...

Grails JAX-RS Calling a class in src/groovy giving error - Message: No signature of method: is applicable for argument types

While developing the rest api using jaxrs plugin I need to create some common class which I have created in "src/groovy". Below is the class class ValidateToken { String validate(String token){ println(token) return "test" } //... In resource file(jaxrs) this is what I am doing def instance=ValidateToken.validate("test") This throws error...

Spring Boot vs. Groovy Templates - can't iterate over a list inside the ModelAndView

I am evaluating Spring Boot for a future application and wanted to use the Groovy templates for their sheer readable beauty. Unfortunately I am having trouble with iterating over a list of objects I am adding to the ModelAndView object returned from the controller. This is my controller: @RestController @RequestMapping("/ships")...

Why isn't split working here?

I'm trying to take a filename that's being passed from a tsv and split it into an array, like so: new File("filenames.tsv").eachLine( { String file_iter -> println file_iter def details = file_iter.split(".") println details }) The output of the printlns: stad.all.16jan15.TP.pwpv [] Why is the array empty? I'm sure I'm...

spring-integration-dsl-groovy-http return null when i use httpGet method

I use spring integration 4.1.4 and spring integration dsl groovy 1.1.0 I included spring integration core, http in dependency. When i am executing spring integration dsl groovy http sample, it throwing null value in console. I am not sure what i missed. Here is my code looks like IntegrationBuilder builder...

calculate max length of each field in csv file using groovy

How can I print out the max length of each field in CSV file? Example input: foo,bar abcd,12345 def,234567 Expected output: Max length of fields: [4, 6] ...

Add floats yields Double

This groovy: float a = 1; float b = 2; def r = a + b; Creates this Java code when reversed from .class with IntelliJ: float a = (float)1; float b = (float)2; Object r = null; double var7 = (double)a + (double)b; r = Double.valueOf(var7); So r contains...

In Groovy, what is the precedence of the membership operator (“in”)

groovy does not list the "in" (membership) binary operator. What is its precedence?

Spring : How to configure tomcat Datasource Programatically in Groovy DAO

I have my tomcat datasource configured in XML as below: <bean id="docDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close" p:driverClassName="${doc.database.driver}" p:url="${doc.database.url}" p:username="${doc.database.user}" p:password="${doc.database.password}" p:validationQuery="select 1" p:testOnBorrow="true" p:minIdle="2" p:maxIdle="4" p:maxActive="6" p:defaultTransactionIsolation="1"> </bean> And my customDAO(groovy class) uses the above datasource as below import...

Match string beginning with ([*>@]|--) ending with one of these

I do have a String like *Task @Context >Delegation --Date and I'd like to extract the strings between the separators *@> and --. *Task @Context >Delegation --Date should yield the four strings Task, Context, Delegation and Date and *Task 9-5 @Co-ntext >Dele-gation --Date 12-5 Task 9-5, Co-ntext, Dele-gation and Date...

How to add quotes into sql where clause in Groovy script?

Collegues, please help me with sql in Groovy. In my SOAP UI groovy script i have sql query: sql.eachRow('select top 1 '+ 'Country, '+ 'from dbo.Address where UPPER(Country) = "JAPAN" ORDER BY NEWID()') Everything was fine till i work without quotes in where clause. After I add UPPER(Country) = "JAPAN"...

Haskell: `==' is not a (visible) method of class

So, when I compile the following piece of code edited: instance (Eq a) => PartOrd a where [] == [] = True (x:xs) == (y:ys) = x==y && xs==ys _==_ = False xs /= ys = not (xs == ys) I get: `==' is not a (visible) method of class...

Java syntax to Groovy syntax

I am not really sure how to translate this to groovy syntax. Have checked this differences with java page already. Thanks! TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String...

using classes in jenkins job dsl

Hi all I have a problem and I can't seem to figure it out. So I'm creating some helper classes for my dsl to use, but it just does not seem to execute any method within these classes. I have created a job with the following dsl in it: class...

gremlin outputs different from as seen on the internet, I think in bytes

How to get gremlin output normal indices along with v Currently it outputs something like this gremlin> g.V WARN com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx - Query requires iterating over all vertices [()]. For better performance, use indexes gremlin> juno = g.addVertex(null); ==>v[128824] gremlin> june = g.addVertex(null); ==>v[128828] gremlin> jape = g.addVertex(null); ==>v[128832] But as...

How does the Groovy compiler work?

Can anyone explain the Groovy compiler works? Does it compile: Groovy code -> Java code -> Bytecode Groovy code -> Bytecode Some other method ...

Any way to make Groovydoc remove (selected) package qualifiers as per Javadoc's 'noqualifier' option?

I've just started generating Groovydoc for a library I'm working on. However, the preponderance of java.lang and java.util and other common package prefixes in the method signatures is obscuring the real intent of the methods. I'd like to be able to generate the Groovydoc without these. As in the (made...

Spock Framework: problems with spying

I have an issue with using Spy in Spock, it either doesn't work as it should or my understanding is wrong so I'm trying to clarify this. Consider this code (Java): public class CallingClass { public String functionOne() { //does stuff return "one"; } public String functionTwo() { String one...

Groovy's @CompileStatic and map constructors

I'm using @CompileStatic for the first time, and confused as to how Groovy's map constructors work in this situation. @CompileStatic class SomeClass { Long id String name public static void main(String[] args) { Map map = new HashMap() map.put("id", 123L) map.put("name", "test file") SomeClass someClass1 = new SomeClass(map) // Does...

Groovy String.toURL is deprecated - why and what should we use instead?

In current groovy versions, the method DefaultGroovyMethods.toURL(String) is marked as deprecated, but without any explanation. Why is it deprecated and what should we use instead? I wanted to use it to easily get a file from HTTP like this: def xml = "".toURL().text ...

Groovy - timestamp from minutes

I have an array or times/values coming back to be in an array like: [0, 60] Which are times in minutes, 0 = 12:00 a.m, 60 = 1:00 a.m. I am wanting to store these in an oracle database as timestamps. How do I convert minutes into timestamps in groovy?...

Groovy 2d array

I want to have a collection like this [item1: [123, 123, 2321], item2: [1231,1222,1313]] I tried using a map like this [ : [] ] but this is not allowed. How can I achieve the following structure. I want to add element using a string as a key: content['item1'] <<...

Chaining Null-Safe Operator

My project has code like the following: params.stringValue?.trim().replaceAll('aa', 'a') We expected that if params.stringValue was null, that both trim() and replaceAll() would not be called. However we were getting a NullPointerException on this line saying that replaceAll() cannot be called on a null Object. We had to change the code...

Cron expression must consist of 6 fields (found 1 in “#{systemEnvironment['db_cron']}”)

I'm trying to set a cron Scheduled annotation as follows: @Scheduled(cron = "#{systemEnvironment['db_cron']}") def void schedule() { } Next set the environment variable as: export db_cron="0 19 21 * * *" However, I get the runtime error: Cron expression must consist of 6 fields (found 1 in "#{systemEnvironment['db_cron']}") What can...

Why does DriverManager.getConnection() lookup fail in GroovyConsole?

The following Groovy script works correctly from the command line. (I successfully get a Connection.) // ---- jdbc_test.groovy import java.sql.* Class.forName("com.mysql.jdbc.Driver") def con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/test", "root", "password") println con > groovy -cp lib\mysql-connector-java-5.1.25-bin.jar script\jdbc_test.groovy [email protected] But if the same script is loaded into GroovyConsole (2.4.3) and run - after...

Get nth child node without knowing node name Groovy

I have xml like this: <node1> <node2> <node3> <node4> <node5> <node6> </node6> <node7> </node7> </node5> </node4> </node3> </node2> </node1> How can I get the name of the 6th node - assuming I don't know the node's name is "node6"? I currently have: def text = <xml from above> def list...

Special Groovy magic re property access and collections / iterables?

I understand what is happening here with the spread operator *. in Groovy (2.4.3): [].class.methods*.name => [add, add, remove, remove, get, ... But why does the leaving the * out produce the same results? [] => [add, add, remove, remove, get, ... I'd have expected that to be interpreted as...

How to get testStep responseAsXml in groovyScript

Concerning soapUI and groovy, I'm trying to get assertion (working) and response both in XML into a variable. I get the error groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep.getResponseAsXml() is applicable for argument types: () values: [] error at line: 6 I have tried adding import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep but still cant figure...

Decode base64 image in Grails [duplicate]

This question already has an answer here: Convert base64 string to image 3 answers I have a post api where I am sending a json string which contain the base64 encoded image.Below is the json string { "imageData":"base64encoded string", "status":"1" } where base64encode string is iVBORw0KGgoAAAANSUhEUgAAAHgAAACgCAIAAABIaz/HAAAAAXNSR0IArs4c6QAA\r\nABxpRE9UAAAAAgAAAAAAAABQAAAAKAAAAFAAAABQAABWL3xrAqoAAEAASURBVHgB\r\nlL2Fe1t7mueZme6uewNGMUu2LNkyySSjDJKZmZkSO8zM7CTmmJnZYbxUVbdgsKp7\r\nqqdrdp I cant post...

why “==” working differently for integer and strings reference? [duplicate]

This question already has an answer here: How do I compare strings in Java? 23 answers May I know how == works here? public class App { public static void main(String[] args) { String s1 = new String("str"); String s2 = new String("str"); System.err.println("why it,s "+String.valueOf(s1==s2)); int i1 =...

Write Spock test cases for Spring boot application

I am working on spring boot application. I have to write test cases for it. I haven't written test cases before, so someone suggested using spock framework for it. I explored spock and i think it is more related to groovy language. Can i write spock test cases for my...

What is faster: equal check or sign check

I wonder which operation works faster: int c = version1.compareTo(version2); This one if (c == 1) or this if (c > 0) Does sign comparasion use just a one bit check and equality comparasion use substraction, or it is not true? For certainty, let's say we work on x86. P.S....