什么是"不可序列化"在这个共享库中,我该如何解决?

时间:2017-06-15 08:41:49

标签: jenkins groovy jenkins-pipeline

使用Jenkins管道插件时,构建失败并出现java.io.NotSerializableException错误,如下所示:

java.io.NotSerializableException: org.codehaus.groovy.control.ErrorCollector
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    ...
Caused by: an exception which occurred:
    in field collector
    in field abnormal
    in field outcome
    in field body
    in field step
    in field thread
    in field this$0
    in field returnAddress
    in field parent
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@6ae7e4f1
    ...
Finished: FAILURE

当我使用带有一些import语句的自定义库时会发生这种情况。我尝试了几件事,比如用@NonCPS封装调用方法,但错误仍然存​​在。

管道脚本

#!groovy
@Library('utils')

pipeline {
    agent any
    stages {
        stage('Run Script') {
            script {
                myScript param1
            }
        }
    }
}

乏/ myScript.groovy

import com.company.jenkins.utils

def call(String param = "test") {
    def libScript = LibScript(this)
    libScript.printMessage("Hello World")
}

的src / COM /公司/詹金斯/ utils的/ LibScript

package com.company.jenkins.utils;

// This import works fine
import groovy.json.*

// This one fails
import groovyx.net.http.RESTClient

class LibScript implements Serializable {
    def steps
    def client

    LibScript(steps) { this.steps = steps }

    def printMessage(String message) { steps.echo "Saying: " message }

    // This also fails
    @NonCPS
    def doSomething() { client = new groovyx.net.http.RESTClient( 'https://somehost/' ) }
}

使用的版本:

  • Jenkins:2.19.3
  • 管道插件:2.5
  • 管道共享Groovy库插件:2.7

2 个答案:

答案 0 :(得分:3)

此错误将来自compilation error。这不是一个很好的堆栈跟踪。但是你有一个non serializable object作为你的变量之一或者在字符串的中间(可以将变量值作为' .." $ var" ..&#39 ;)。为此,我附上了两个链接。请仔细阅读,你会明白出了什么问题。请一步一步地了解哪里出错了。

1)https://issues.jenkins-ci.org/browse/JENKINS-40109

2)https://coderwall.com/p/zvsh5q/jenkins-load-command-can-t-found-why-i-have-a-java-io-notserializableexception

答案 1 :(得分:1)

如接受的答案所述,此(非描述性)错误表示某种编译错误。然后问题是跟踪编译错误是什么,因为错误消息基本上没有告诉你。

在使用声明性管道时,似乎只会出现这种非描述性编译错误消息。如果要切换到脚本化管道,则会收到更具体的错误消息。

但是,如果使用try catch块包装有问题的代码,则可以从声明性管道中获取更多描述性错误。作为我的一些代码的一个例子,我从这个管道代码块中缩小了NotSerializableException:

post { always { notifyOnBuildResults currentBuild : currentBuild } }

我将代码更改为此

post { always { script { try { notifyOnBuildResults currentBuild : currentBuild } catch (Exception e) { echo e.toString() } } } }

并且能够看到特定的编译错误。