Writing Pipeline steps - Help

188 views
Skip to first unread message

sohl

unread,
Feb 23, 2017, 1:34:28 PM2/23/17
to Jenkins Developers
I'm following https://github.com/jenkinsci/workflow-step-api-plugin/#writing-pipeline-steps

It advises the following implementation:

class MyStep extends Step {
@Extension
public static final class DescriptorImpl extends StepDescriptor {
@Override
public Set<? extends Class<?>> getRequiredContext() { return set; }
}

private static class Execution extends SynchronousNonBlockingStepExecution<Object> {
@Override
protected Object run() throws Exception { return object; }
}
@Override
public StepExecution start(StepContext context) throws Exception {
return new StepExecution(context); 
}
}

Some of the questions I'm struggling to figure out:

MyStep.start
is this method invoked automatically by Jenkins? If Yes, then
Why to use Execution when all the logic of the plugin can be done here?
MyStep.DescriptorImpl.getRequiredContext
What has to go here? Set of what classes needs to be provided?
MyStep.Execution    Note 'private static'
how is this supposed to be instantiated?.
how to pass handle of this to Jenkins?.
how to pass/get parameters from MyStep to Execution?
MyStep.Execution.run
Is this method called automatically by Jenkins (through SynchronousNonBlockingStepExecution.start)?

Note that all the existing plugins I checked so far use deprecated API, so not much help.

Advise is highly appreciated.

sohl

unread,
Feb 23, 2017, 4:25:13 PM2/23/17
to Jenkins Developers
Figured out some of the questions
MyStep.start   is invoked automatically

MyStep.Execution   apparently has to be instantiated from the outer class:

@Override
public StepExecution start(StepContext context) throws Exception {
return new Execution(context);    // here also other paramters could be supplied by modifying the Execution constructor correspondingly e.g.
//  return new Execution (context, this);
}

MyStep.Execution.run is called automatically after the above instantiation.

Now the remaining problems:

MyStep.DescriptorImpl.getRequiredContext      how to implement?

With the naive implementation
Execution.run () {
     return "Run OK"
}

The following ERROR is thrown:
-------------------------------------------
Feb 23, 2017 4:07:31 PM org.jenkinsci.plugins.workflow.cps.CpsThreadGroup saveProgramIfPossible
WARNING: program state save failed
java.io.IOException: Failed to persist C:\a02_projects\jenkins\saltapi-step\work\jobs\xx_pipe\builds\11\program.dat
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:466)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:427)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgramIfPossible(CpsThreadGroup.java:415)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:360)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:80)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:240)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:228)
        at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
        at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.io.NotSerializableException: org.jenkinsci.plugins.workflow.job.WorkflowRun
        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.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
        at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
        at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
        at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
        at java.util.TreeMap.writeObject(TreeMap.java:2433)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
        at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
        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.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
        at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
        at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:132)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:452)
        ... 15 more
Caused by: an exception which occurred:
        in field build
        in field step
        in field threads
        in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@1af4f1a7
-------------------------------------------

Suggestions?

Jesse Glick

unread,
Feb 24, 2017, 9:52:19 AM2/24/17
to Jenkins Dev
On Thu, Feb 23, 2017 at 4:25 PM, sohl <mahr...@gmail.com> wrote:
> MyStep.DescriptorImpl.getRequiredContext how to implement?

For any usages of `StepContext.get(Class)` from your `StepExecution`,
list that class—unless you can handle a null return value.

> java.io.NotSerializableException: org.jenkinsci.plugins.workflow.job.WorkflowRun

Presumably you had a non-`transient` field of type `Run` somewhere. Do
not store it; use `context.get(Run.class)` whenever required.

sohl

unread,
Feb 24, 2017, 11:01:22 AM2/24/17
to Jenkins Developers
That was it! Indeed I saved Run as a private variable in Execution.run. Removed and everything worked!
Thanks a lot for the help.
Reply all
Reply to author
Forward
0 new messages