Sviatlana
Sviatlana

Reputation: 1888

java.io.NotSerializableException: hudson.model.FreeStyleProject

I am trying to execute pipeline script in Jenkins. Here is my script:

import com.cloudbees.groovy.cps.NonCPS
@NonCPS
def getJobVariable(jobName,varName){ 
    job = Jenkins.instance.getItemByFullName(jobName)
        newJob = job.getLastBuild()
    return newJob.getEnvVars().get(varName,null)
}




node{
    stage 'props'

    api = build job: 'Props'
    buildID =  api.getNumber()
    build job: 'Parameterized', parameters: [[$class: 'StringParameterValue', name: 'string_parameter', value: getJobVariable('Props','filename')]];

}

But I am constantly getting NotSerializableException. I guess, something wrong in my getJobVariable method. Please, help

Upvotes: 14

Views: 15824

Answers (4)

MadHatter
MadHatter

Reputation: 395

The existing answers are really helpful, thank all of you. I get the same issue, and adding a def to the var, or set the var to null, both can fix my issue.

I just want to add some of my own understanding.
In Jenkins, define a var without "def", the var is considered as a global var.

@NonCPS
def rename(nodeName, needOffline, reason=''){
    hudson = hudson.model.Hudson.instance
    nodeObj = hudson.slaves.findAll { it.nodeName == nodeName }
    // some other logic
    hudson.save()
}

In the above example, both hudson and nodeObj are global variables, and non-serializable, so will lead to java.io.NotSerializableException.

Solution 1, add def to the two variables(So the variables are considered as local variables):

@NonCPS
def rename(nodeName, needOffline, reason=''){
    def hudson = hudson.model.Hudson.instance
    def nodeObj = hudson.slaves.findAll { it.nodeName == nodeName }
    // some other logic
    hudson.save()
}

Solution 2, set the two variables to null after they are used:

@NonCPS
def rename(nodeName, needOffline, reason=''){
    hudson = hudson.model.Hudson.instance
    nodeObj = hudson.slaves.findAll { it.nodeName == nodeName }
    // some other logic
    hudson.save()
    hudson = null
    nodeObj = null
}

Personally, I prefer the first approach, if I define the variable as local with def at the beginning, I no longer need to worry about the variable scope any more.

Upvotes: 0

anyone.can.test
anyone.can.test

Reputation: 109

Add the following:

job = null

after

newJob = job.getLastBuild()

Upvotes: 4

ManishSingh
ManishSingh

Reputation: 1166

Jenkins stages needs to be serialized so that they can survive job & jenkins restarts. Now if you have some variable which have NotSerializable still exists after the stage [Pipeline] // stage then we get this error.

So we should set the variable to null before it touches the stage boundary

further read https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

Upvotes: 4

Algorys
Algorys

Reputation: 1790

I've made some tests, cause I've the same issue in my pipeline jobs (for Matrix).

The solution is to put def before job or the name of Object (here Job) before your declaration.

After the NotSerializableException disappear.

If this does not solve your problem, you can also add @NonCPS flag before your declaration. See the official documentation: serializing-local-variables.

Upvotes: 20

Related Questions