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

Pipeline implementing readObject/writeObject fails with ProxyException CpsCallableInvocation

    • Icon: Improvement Improvement
    • Resolution: Unresolved
    • Icon: Minor Minor
    • workflow-cps-plugin

      I have a set of steps which share a configuration instance. The configuration is implemented as Singleton. Now, I would like to serialize this @Singleton to support the resume feature of Jenkins pipelines. Currently, all runtime configurations are gone, if the Jenkins is restarted in between.

      Since statics aren't serialized, I implemented readObject and writeObject. What ever I tried, i came across the ProxyException: 

      hudson.remoting.ProxyException: CpsCallableInvocation{methodName=writeObject, call=com.cloudbees.groovy.cps.impl.CpsFunction@1bc872bf, receiver=my.simple.TestPipelineEnvironment@40f84a32, arguments=[org.jboss.marshalling.river.RiverObjectOutputStream@8ad5752]}
      

      In the code below, I implemented the simple POGO my.simple.TestPipelineEnvironment.groovy with readObject and writeObject. I dropped the @Singleton to reduce complexity.

      package my.simple;
      
      public class TestPipelineEnvironment implements Serializable {
      
      	private void writeObject(ObjectOutputStream oos) throws IOException {
      		System.out.println("Custom serialization logic invoked.");
      		oos.defaultWriteObject();
      	}
      	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
      		System.out.println("Custom deserialization logic invoked.");
      		ois.defaultReadObject();
      	}
      
      	private Map valueMap = [:]
      
      	void setValue(String property, value) {
      		valueMap[property] = value
      	}
      
      	def getValue(String property) {
      		return valueMap.get(property)
      	}
      }
      
      
      

      It is initialized and accessible by the step vars/testPipelineEnvironment.groovy

       

      import my.simple.TestPipelineEnvironment
      
      class testPipelineEnvironment implements Serializable {
      
          private static final long serialVersionUID = -113665469917946598L;
      
          private TestPipelineEnvironment instance= new TestPipelineEnvironment();
      
          private TestPipelineEnvironment getCPE() {
              return instance;
          }
      
          Map getValueMap() {
              getCPE().valueMap
          }
      
          void setValue(String property, value) {
              valueMap[property] = value
          }
      
          def getValue(String property) {
              return valueMap.get(property)
          }
      }

      The Jenkinsfile fails

       

      @Library('piper-lib-rodibrin') _
      node() {
        stage('prepare') { 
          testPipelineEnvironment.setValue("key","value") echo "value:" + testPipelineEnvironment.getValue("key") 
        }
      }
      

      with

       

      ...
      [Pipeline] echo
       value:value
       [Pipeline] }
       [Pipeline] End of Pipeline
       hudson.remoting.ProxyException: CpsCallableInvocation{methodName=writeObject, call=com.cloudbees.groovy.cps.impl.CpsFunction@1bc872bf, receiver=my.simple.TestPipelineEnvironment@40f84a32, arguments=[org.jboss.marshalling.river.RiverObjectOutputStream@8ad5752]}
       Finished: FAILURE
      

       

          [JENKINS-60223] Pipeline implementing readObject/writeObject fails with ProxyException CpsCallableInvocation

          The same with restoring the pipeline object after the jenkins (2.204.2 with minimal plugins) stop/start:

          • Pipeline log error:
            [Pipeline] input
            continue?
            Proceed or Abort
            Resuming build at Sun Feb 16 01:02:36 UTC 2020 after Jenkins restart
            Waiting to resume part of mpl-build #4: Finished waiting
            [Pipeline] End of Pipeline
            hudson.remoting.ProxyException: CpsCallableInvocation{methodName=readObject, call=com.cloudbees.groovy.cps.impl.CpsFunction@7505dedb, receiver=com.griddynamics.devops.mpl.MPLManager@372524ed, arguments=[org.jboss.marshalling.river.RiverObjectInputStream@6c0dd7d4]}
            Caused: hudson.remoting.ProxyException: java.io.IOException: Failed to load build state
            	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$3.onSuccess(CpsFlowExecution.java:855)
            	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$3.onSuccess(CpsFlowExecution.java:853)
            	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$4$1.run(CpsFlowExecution.java:907)
            	at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$1.run(CpsVmExecutorService.java:38)
            	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
            	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
            	at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
            	at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
            	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
            	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
            	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
            	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
            	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
            	at java.base/java.lang.Thread.run(Thread.java:834)
            Finished: FAILURE
            
          • Jenkins output:
            2020-02-16 01:02:36.026+0000 [id=34]    INFO    hudson.WebAppMain$3#run: Jenkins is fully up and running
            2020-02-16 01:02:42.484+0000 [id=161]   WARNING jenkins.security.ClassFilterImpl#notifyRejected: com.cloudbees.groovy.cps.impl.CpsFunction in file:/var/jenkins
            _home/plugins/workflow-cps/WEB-INF/lib/groovy-cps-1.32.jar might be dangerous, so rejecting; see https://jenkins.io/redirect/class-filter/
            2020-02-16 01:02:42.595+0000 [id=179]   WARNING o.j.p.w.cps.CpsThreadGroup#unexport: double unexport of 1
            2020-02-16 01:02:42.597+0000 [id=161]   INFO    o.j.p.workflow.job.WorkflowRun#finish: mpl-build #4 completed: FAILURE
            

          Sergei Parshev added a comment - The same with restoring the pipeline object after the jenkins (2.204.2 with minimal plugins) stop/start: Pipeline log error: [Pipeline] input continue? Proceed or Abort Resuming build at Sun Feb 16 01:02:36 UTC 2020 after Jenkins restart Waiting to resume part of mpl-build #4: Finished waiting [Pipeline] End of Pipeline hudson.remoting.ProxyException: CpsCallableInvocation{methodName=readObject, call=com.cloudbees.groovy.cps.impl.CpsFunction@7505dedb, receiver=com.griddynamics.devops.mpl.MPLManager@372524ed, arguments=[org.jboss.marshalling.river.RiverObjectInputStream@6c0dd7d4]} Caused: hudson.remoting.ProxyException: java.io.IOException: Failed to load build state at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$3.onSuccess(CpsFlowExecution.java:855) at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$3.onSuccess(CpsFlowExecution.java:853) at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution$4$1.run(CpsFlowExecution.java:907) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$1.run(CpsVmExecutorService.java:38) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28) at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Finished: FAILURE Jenkins output: 2020-02-16 01:02:36.026+0000 [id=34] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running 2020-02-16 01:02:42.484+0000 [id=161] WARNING jenkins.security.ClassFilterImpl#notifyRejected: com.cloudbees.groovy.cps.impl.CpsFunction in file:/var/jenkins _home/plugins/workflow-cps/WEB-INF/lib/groovy-cps-1.32.jar might be dangerous, so rejecting; see https://jenkins.io/redirect/class-filter/ 2020-02-16 01:02:42.595+0000 [id=179] WARNING o.j.p.w.cps.CpsThreadGroup#unexport: double unexport of 1 2020-02-16 01:02:42.597+0000 [id=161] INFO o.j.p.workflow.job.WorkflowRun#finish: mpl-build #4 completed: FAILURE

          rodibrin, actually @NonCPS helped, got it from `Similar Issues`: JENKINS-55113

            @NonCPS
            private void readObject(java.io.ObjectInputStream inp) throws IOException, ClassNotFoundException {
              System.out.println("Custom deserialization logic invoked.")
              inp.defaultReadObject()
            }
          

          From Jenkins output:

          2020-02-16 01:23:44.958+0000 [id=34]    INFO    hudson.WebAppMain$3#run: Jenkins is fully up and running
          Custom deserialization logic invoked.
          

          Sergei Parshev added a comment - rodibrin , actually @NonCPS helped, got it from `Similar Issues`: JENKINS-55113 @NonCPS private void readObject(java.io.ObjectInputStream inp) throws IOException, ClassNotFoundException { System.out.println("Custom deserialization logic invoked.") inp.defaultReadObject() } From Jenkins output: 2020-02-16 01:23:44.958+0000 [id=34] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running Custom deserialization logic invoked.

          Sergei, many thanks, it's simple and it works.

          Interestingly, Jenkins does not serialize a multi branch pipeline, so i can't use read/writeObject to resume from stage, but this another story.... 

          Roland Stengel added a comment - Sergei, many thanks, it's simple and it works. Interestingly, Jenkins does not serialize a multi branch pipeline, so i can't use read/writeObject to resume from stage, but this another story.... 

            Unassigned Unassigned
            rodibrin Roland Stengel
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: