[JIRA] (JENKINS-61748) Trying to use PriorityQueue.add with custom classes winds up catching CustomClass.compareTo in scripted pipelines

7 views
Skip to first unread message

killspire@gmail.com (JIRA)

unread,
Mar 30, 2020, 7:41:03 PM3/30/20
to jenkinsc...@googlegroups.com
Ryan Fenton-Garcia created an issue
 
Jenkins / Bug JENKINS-61748
Trying to use PriorityQueue.add with custom classes winds up catching CustomClass.compareTo in scripted pipelines
Issue Type: Bug Bug
Assignee: Unassigned
Components: workflow-cps-plugin
Created: 2020-03-30 23:40
Environment: Windows Server 2016
Jenkins: 2.204.5
Pipeline: 2.6
Labels: pipeline workflow-cps-plugin java queue
Priority: Minor Minor
Reporter: Ryan Fenton-Garcia

I'm attempting to make use of the native Java priority queue in a pipeline job by defining the following custom class 

class PriorityClosure implements Comparable<PriorityClosure> {
  int priority
  Closure closure

  int compareTo(PriorityClosure o) { priority <=> o?.priority }

  PriorityClosure(priority, closure) {
    this.priority = priority
    this.closure = closure
  }
}

and then attempting to run the following function

def someFunction() {
  def testQueue = new PriorityQueue<PriorityClosure>()
  for (int i = 0; i < 23; i++) {
    int staticIteratorReference = i
    testQueue.add(new PriorityClosure(
      staticIteratorReference,
      {
        println "this is a test"
      }
    ))
  }

  println "Test Queue is: ${testQueue}"
}

I would expect to get a priority queue with all of my stuff in it, but instead, checking the output console, I receive the following:

[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/

and then a Queue that looks like this

[2020-03-30T23:13:51.580Z] [Pipeline] echo[2020-03-30T23:13:51.580Z] Test Queue is: [PriorityClosure@5ae890da, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]

I realise that using the native PriorityQueue inside of a Jenkins job may be an incredibly niche use case. My attempts to google what exactly is going wrong here as well as this error has returned a net 0 results. Another weird thing I've noticed is that the first add seems to work fine. One item gets added to the PriorityQueue and every add after that suffers from the catching PriorityClosure.compareTo error. 

Does anyone know what's going on here? I'm currently assuming this is a bug, but I realise this could also be a me problem. 

 

Add Comment Add Comment
 
This message was sent by Atlassian Jira (v7.13.12#713012-sha1:6e07c38)
Atlassian logo

killspire@gmail.com (JIRA)

unread,
Mar 30, 2020, 7:45:02 PM3/30/20
to jenkinsc...@googlegroups.com
Ryan Fenton-Garcia updated an issue
Change By: Ryan Fenton-Garcia
I'm attempting to make use of the native Java priority queue in a pipeline job by defining the following custom class 
{code:java}
import java.lang.Comparable

class PriorityClosure implements Comparable<PriorityClosure> {
  int priority
  Closure closure

  int compareTo(PriorityClosure o) { priority <=> o?.priority }

  PriorityClosure(priority, closure) {
    this.priority = priority
    this.closure = closure
  }
}
{code}

and then attempting to run the following function
{code:java}
import

def someFunction() {
  def testQueue = new PriorityQueue<PriorityClosure>()
  for (int i = 0; i < 23; i++) {
    int staticIteratorReference = i
    testQueue.add(new PriorityClosure(
      staticIteratorReference,
      {
        println "this is a test"
      }
    ))
  }

  println "Test Queue is: ${testQueue}"
}
{code}

I would expect to get a priority queue with all of my stuff in it, but instead, checking the output console, I receive the following:
{code:java}

[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.564Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
[2020-03-30T23:13:51.580Z] expected to call java.util.PriorityQueue.add but wound up catching PriorityClosure.compareTo; see: https://jenkins.io/redirect/pipeline-cps-method-mismatches/
{code}

and then a Queue that looks like this
{code:java}

[2020-03-30T23:13:51.580Z] [Pipeline] echo[2020-03-30T23:13:51.580Z] Test Queue is: [PriorityClosure@5ae890da, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
{code}

I realise that using the native PriorityQueue inside of a Jenkins job may be an incredibly niche use case. My attempts to google what exactly is going wrong here as well as this error has returned a net 0 results. Another weird thing I've noticed is that the first add seems to work fine. One item gets added to the PriorityQueue and every add after that suffers from the catching PriorityClosure.compareTo error. 

Does anyone know what's going on here? I'm currently assuming this is a bug, but I realise this could also be a me problem. 

 

killspire@gmail.com (JIRA)

unread,
Mar 30, 2020, 7:45:03 PM3/30/20
to jenkinsc...@googlegroups.com
Ryan Fenton-Garcia updated an issue
I'm attempting to make use of the native Java priority queue in a pipeline job by defining the following custom class 
{code:java}
import java.lang.Comparable

class PriorityClosure implements Comparable<PriorityClosure> {
  int priority
  Closure closure

  int compareTo(PriorityClosure o) { priority <=> o?.priority }

  PriorityClosure(priority, closure) {
    this.priority = priority
    this.closure = closure
  }
}
{code}
and then attempting to run the following function
{code:java}
import

java.util.PriorityQueue

killspire@gmail.com (JIRA)

unread,
Mar 31, 2020, 1:09:05 PM3/31/20
to jenkinsc...@googlegroups.com

dnusbaum@cloudbees.com (JIRA)

unread,
Apr 7, 2020, 3:46:04 PM4/7/20
to jenkinsc...@googlegroups.com

Please take a look at the content at the link in the error message, specifically the section "Override of non-CPS-transformed methods". I think that in your case, if you add @NonCPS to this code, you will get the expected behavior:

@NonCPS // Add this annotation
int compareTo(PriorityClosure o) { priority <=> o?.priority }
 
                                                            

The reason you need to do this is that your PriorityClosure class, which is defined in a Pipeline and so all of its methods are CPS-transformed, is being passed to PriorityQueue, which is a normal Java standard library class and so is not CPS-transformed, so PriorityQueue.add is not able to call PriorityClosure.compareTo correctly.

dnusbaum@cloudbees.com (JIRA)

unread,
Apr 7, 2020, 3:46:05 PM4/7/20
to jenkinsc...@googlegroups.com
Devin Nusbaum edited a comment on Bug JENKINS-61748
Please take a look at [the content at the link in the error message|https://jenkins.io/redirect/pipeline-cps-method-mismatches/], specifically the section " Override Overrides of non-CPS-transformed methods". I think that in your case, if you add {{@NonCPS}} to this code, you will get the expected behavior:
{code:java}

@NonCPS // Add this annotation
int compareTo(PriorityClosure o) { priority <=> o?.priority }
{code}
The reason you need to do this is that your {{PriorityClosure}} class, which is defined in a Pipeline and so all of its methods are CPS-transformed, is being passed to {{PriorityQueue}}, which is a normal Java standard library class and so is not CPS-transformed, so {{PriorityQueue.add}} is not able to call {{PriorityClosure.compareTo}} correctly.
Reply all
Reply to author
Forward
0 new messages