Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-61748

Trying to use PriorityQueue.add with custom classes winds up catching CustomClass.compareTo in scripted pipelines

    XMLWordPrintable

    Details

    • Similar Issues:

      Description

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

      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
        }
      }
      

      and then attempting to run the following function

      import java.util.PriorityQueue
      
      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. 

       

        Attachments

          Activity

          Hide
          rjfenton Ryan Fenton-Garcia added a comment -

          I've done some digging, and I think this is related to:
          https://issues.jenkins-ci.org/browse/JENKINS-44924

          But I'm not entirely sure. 

          Show
          rjfenton Ryan Fenton-Garcia added a comment - I've done some digging, and I think this is related to: https://issues.jenkins-ci.org/browse/JENKINS-44924 But I'm not entirely sure. 
          Hide
          dnusbaum Devin Nusbaum added a comment - - edited

          Please take a look at the content at the link in the error message, specifically the section "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:

          @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.

          Show
          dnusbaum Devin Nusbaum added a comment - - edited Please take a look at  the content at the link in the error message , specifically the section "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: @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.

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            rjfenton Ryan Fenton-Garcia
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated: