Agree with your point.
I have change the code accordingly. Compiles properly through Maven. But
now Jenkins at Runtime throwing exception when saving the job
configuration, saying -
Caused by: java.lang.IllegalArgumentException: Failed to instantiate class
com.oracle.siebel.jenkins.ABC from
{"enableText1":{"text1":"hello"},"enableText2":{"text2":"kul"},"enableText3":{"text3":"bhushan"},"stapler-class":"com.oracle.siebel.jenkins.ABC","$class":"com.oracle.siebel.jenkins.ABC"}
at
org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:674)
at org.kohsuke.stapler.RequestImpl.bindJSON(RequestImpl.java:476)
at org.kohsuke.stapler.RequestImpl.bindJSON(RequestImpl.java:472)
at hudson.model.Descriptor.newInstance(Descriptor.java:588)
... 81 more
Caused by: org.kohsuke.stapler.NoStaplerConstructorException: There's no
@DataBoundConstructor on any constructor of class
com.oracle.siebel.jenkins.ABC
at
org.kohsuke.stapler.ClassDescriptor.loadConstructorParamNames(ClassDescriptor.java:177)
at org.kohsuke.stapler.RequestImpl.instantiate(RequestImpl.java:756)
at org.kohsuke.stapler.RequestImpl.access$200(RequestImpl.java:81)
at
org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:672)
... 84 more
*New Java File*
import org.kohsuke.stapler.DataBoundConstructor;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.tasks.Messages;
import hudson.Proc;
import hudson.Util;
import hudson.EnvVars;
import hudson.model.AbstractBuild;
import hudson.model.AbstractDescribableImpl;
import hudson.model.BuildListener;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.remoting.ChannelClosedException;
import hudson.model.AbstractProject;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import hudson.tasks.CommandInterpreter;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
public class BuildStepCreator extends Builder{
private String text1, text2, text3;
public String getText1(){
return text1;
}
public String getText2(){
return text2;
}
public String getText3(){
return text3;
}
@DataBoundConstructor
public BuildStepCreator(OptionalTextBlock1 enableText1,
OptionalTextBlock2 enableText2, OptionalTextBlock3 enableText3) {
this.text1 = (enableText1 != null) ? enableText1.text1 : null;
this.text2 = (enableText2 != null) ? enableText2.text2 : null;
this.text3 = (enableText3 != null) ? enableText3.text3 : null;
}
public static class OptionalTextBlock1 {
private String text1;
@DataBoundConstructor
public OptionalTextBlock1(String text1) {
this.text1 = text1;
}
}
public static class OptionalTextBlock2 {
private String text2;
@DataBoundConstructor
public OptionalTextBlock2(String text2) {
this.text2 = text2;
}
}
public static class OptionalTextBlock3 {
private String text3;
@DataBoundConstructor
public OptionalTextBlock3(String text3) {
this.text3 = text3;
}
}
}
abstract class ABC extends BuildStepCreator{
public ABC(OptionalTextBlock1 enableText1, OptionalTextBlock2
enableText2, OptionalTextBlock3 enableText3) {
super(enableText1, enableText2, enableText3);
// TODO Auto-generated constructor stub
}
public abstract String[] buildCommandLine(FilePath script);
protected abstract String getContents();
protected abstract String getFileExtension();
@Extension
public static final class DescriptorImpl extends
BuildStepDescriptor<Builder>{
@Override
public boolean isApplicable(Class<? extends AbstractProject>
jobType) {
// TODO Auto-generated method stub
return true;
}
@Override
public String getDisplayName() {
// TODO Auto-generated method stub
return "Job Orchestration";
}
}
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher,
BuildListener listener) throws InterruptedException {
return perform(build,launcher,(TaskListener)listener);
}
/**
* Determines whether a non-zero exit code from the process should
change the build
* status to {@link Result#UNSTABLE} instead of default {@link
Result#FAILURE}.
*
* Changing to {@link Result#UNSTABLE} does not abort the build, next
steps are continued.
*
*/
protected boolean isErrorlevelForUnstableBuild(int exitCode) {
return false;
}
public boolean perform(AbstractBuild<?,?> build, Launcher launcher,
TaskListener listener) throws InterruptedException{
FilePath ws = build.getWorkspace();
if (ws == null) {
Node node = build.getBuiltOn();
if (node == null) {
throw new NullPointerException("no such build node: " +
build.getBuiltOnStr());
}
throw new NullPointerException("no workspace from node " + node
+ " which is computer " + node.toComputer() + " and has channel " +
node.getChannel());
}
FilePath script=null;
int r = -1;
try {
try {
script = createScriptFile(ws);
} catch (IOException e) {
Util.displayIOException(e,listener);
e.printStackTrace(listener.fatalError(Messages.CommandInterpreter_UnableToProduceScript()));
return false;
}
try {
EnvVars envVars = build.getEnvironment(listener);
// on Windows environment variables are converted to all
upper case,
// but no such conversions are done on Unix, so to make
this cross-platform,
// convert variables to all upper cases.
for(Map.Entry<String,String> e :
build.getBuildVariables().entrySet())
envVars.put(e.getKey(),e.getValue());
r =
join(launcher.launch().cmds(buildCommandLine(script)).envs(envVars).stdout(listener).pwd(ws).start());
if(isErrorlevelForUnstableBuild(r)) {
build.setResult(Result.FAILURE);
r = 0;
}
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages.CommandInterpreter_CommandFailed()));
}
return r==0;
} finally {
try {
if(script!=null)
script.delete();
} catch (IOException e) {
if (r==-1 && e.getCause() instanceof
ChannelClosedException) {
// JENKINS-5073
// r==-1 only when the execution of the command
resulted in IOException,
// and we've already reported that error. A common
error there is channel
// losing a connection, and in that case we don't want
to confuse users
// by reporting the 2nd problem. Technically the 1st
exception may not be
// a channel closed error, but that's rare enough, and
JENKINS-5073 is common enough
// that this suppressing of the error would be justified
LOGGER.log(Level.FINE, "Script deletion failed", e);
} else {
Util.displayIOException(e,listener);
e.printStackTrace(
listener.fatalError(Messages.CommandInterpreter_UnableToDelete(script)) );
}
} catch (Exception e) {
e.printStackTrace(
listener.fatalError(Messages.CommandInterpreter_UnableToDelete(script)) );
}
}
}
/**
* Reports the exit code from the process.
*
* This allows subtypes to treat the exit code differently (for example
by treating non-zero exit code
* as if it's zero, or to set the status to {@link Result#UNSTABLE}).
Any non-zero exit code will cause
* the build step to fail. Use {@link #isErrorlevelForUnstableBuild(int
exitCode)} to redefine the default
* behaviour.
*
* @since 1.549
*/
protected int join(Proc p) throws IOException, InterruptedException {
return p.join();
}
/**
* Creates a script file in a temporary name in the specified directory.
*/
public FilePath createScriptFile(@Nonnull FilePath dir) throws
IOException, InterruptedException {
return dir.createTextTempFile("hudson", getFileExtension(),
getContents(), false);
}
private static final Logger LOGGER =
Logger.getLogger(CommandInterpreter.class.getName());
}
On Wednesday, 16 November 2016 23:00:36 UTC+5:30, Robert Sandell wrote:
>
> Abstract classes cannot be instanciated, so you can't annotate the
> constructor with DataBoundConstructor since the class can't be directly
> instanciated but will need to be subclassed.
>
> /B
>
> On Wed, Nov 16, 2016 at 3:59 PM, Kul Bhushan Srivastava <[email protected]
> <javascript:>> wrote:
>
>> Thanks Robert.
>>
>> I am facing maven compilation issue. Saying @DataBoundConstructor cannot
>> be used inside abstract class.
>>
>> Please suggest.
>>
>> My Java File:
>>
>> import org.kohsuke.stapler.DataBoundConstructor;
>> import hudson.Extension;
>> import hudson.FilePath;
>> import hudson.Launcher;
>> import hudson.tasks.Messages;
>> import hudson.Proc;
>> import hudson.Util;
>> import hudson.EnvVars;
>> import hudson.model.AbstractBuild;
>> import hudson.model.BuildListener;
>> import hudson.model.Node;
>> import hudson.model.Result;
>> import hudson.model.TaskListener;
>> import hudson.remoting.ChannelClosedException;
>> import hudson.model.AbstractProject;
>> import hudson.tasks.BuildStepDescriptor;
>> import hudson.tasks.Builder;
>> import hudson.tasks.CommandInterpreter;
>> import java.io.IOException;
>> import java.util.Map;
>> import java.util.logging.Level;
>> import java.util.logging.Logger;
>> import javax.annotation.Nonnull;
>>
>> public abstract class BuildStepCreator extends Builder {
>>
>> private String text1, text2, text3;
>>
>> public String getText1(){
>> return text1;
>> }
>> public String getText2(){
>> return text2;
>> }
>> public String getText3(){
>> return text3;
>> }
>>
>>
>> @DataBoundConstructor
>> public BuildStepCreator(OptionalTextBlock1 enableText1,
>> OptionalTextBlock2 enableText2, OptionalTextBlock3 enableText3) {
>> this.text1 = (enableText1 != null) ? enableText1.text1 : null;
>> this.text2 = (enableText2 != null) ? enableText2.text2 : null;
>> this.text3 = (enableText3 != null) ? enableText3.text3 : null;
>> }
>>
>> public static class OptionalTextBlock1 {
>> private String text1;
>> @DataBoundConstructor
>> public OptionalTextBlock1(String text1) {
>> this.text1 = text1;
>> }
>> }
>> public static class OptionalTextBlock2 {
>> private String text2;
>> @DataBoundConstructor
>> public OptionalTextBlock2(String text2) {
>> this.text2 = text2;
>> }
>> }
>> public static class OptionalTextBlock3 {
>> private String text3;
>> @DataBoundConstructor
>> public OptionalTextBlock3(String text3) {
>> this.text3 = text3;
>> }
>> }
>>
>> @Extension
>> public static final class DescriptorImpl extends
>> BuildStepDescriptor<Builder>{
>>
>> /*public FormValidation doCheckTask(@QueryParameter String value){
>> try{
>> if(value.equalsIgnoreCase(null) ||
>> value.equalsIgnoreCase("")){
>> return FormValidation.error("Invalid Details.");
>> }
>> }catch(Exception e){
>> return FormValidation.error("Error validating the form
>> details.");
>> }
>> return FormValidation.ok();
>> }
>>
>> public FormValidation doCheckGoal(@QueryParameter String value){
>> try{
>> Integer.parseInt(value);
>> }catch(Exception e){
>> return FormValidation.error("Please provide integer in
>> the Goal.");
>> }
>> return FormValidation.ok();
>> }*/
>>
>> @Override
>> public boolean isApplicable(Class<? extends AbstractProject>
>> jobType) {
>> // TODO Auto-generated method stub
>> return true;
>> }
>>
>> @Override
>> public String getDisplayName() {
>> // TODO Auto-generated method stub
>> return "Job Orchestration";
>> }
>> }
>>
>> /*@Override
>> public boolean perform(hudson.model.AbstractBuild build,
>> hudson.Launcher launcher, hudson.model.BuildListener listener) {
>> listener.getLogger().println("OptionalBlockSampleBuilder " +
>> text1);
>> return true;
>> }*/
>>
>> @Override
>> public boolean perform(AbstractBuild<?,?> build, Launcher launcher,
>> BuildListener listener) throws InterruptedException {
>> return perform(build,launcher,(TaskListener)listener);
>> }
>>
>> /**
>> * Determines whether a non-zero exit code from the process should
>> change the build
>> * status to {@link Result#UNSTABLE} instead of default {@link
>> Result#FAILURE}.
>> *
>> * Changing to {@link Result#UNSTABLE} does not abort the build, next
>> steps are continued.
>> *
>> */
>> protected boolean isErrorlevelForUnstableBuild(int exitCode) {
>> return false;
>> }
>>
>> public boolean perform(AbstractBuild<?,?> build, Launcher launcher,
>> TaskListener listener) throws InterruptedException{
>> FilePath ws = build.getWorkspace();
>> if (ws == null) {
>> Node node = build.getBuiltOn();
>> if (node == null) {
>> throw new NullPointerException("no such build node: " +
>> build.getBuiltOnStr());
>> }
>> throw new NullPointerException("no workspace from node " +
>> node + " which is computer " + node.toComputer() + " and has channel " +
>> node.getChannel());
>> }
>> FilePath script=null;
>> int r = -1;
>> try {
>> try {
>> script = createScriptFile(ws);
>> } catch (IOException e) {
>> Util.displayIOException(e,listener);
>>
>> e.printStackTrace(listener.fatalError(Messages.CommandInterpreter_UnableToProduceScript()));
>> return false;
>> }
>>
>> try {
>> EnvVars envVars = build.getEnvironment(listener);
>> // on Windows environment variables are converted to all
>> upper case,
>> // but no such conversions are done on Unix, so to make
>> this cross-platform,
>> // convert variables to all upper cases.
>> for(Map.Entry<String,String> e :
>> build.getBuildVariables().entrySet())
>> envVars.put(e.getKey(),e.getValue());
>>
>> r =
>> join(launcher.launch().cmds(buildCommandLine(script)).envs(envVars).stdout(listener).pwd(ws).start());
>>
>> if(isErrorlevelForUnstableBuild(r)) {
>> build.setResult(Result.UNSTABLE);
>> r = 0;
>> }
>> } catch (IOException e) {
>> Util.displayIOException(e, listener);
>>
>> e.printStackTrace(listener.fatalError(Messages.CommandInterpreter_CommandFailed()));
>> }
>> return r==0;
>> } finally {
>> try {
>> if(script!=null)
>> script.delete();
>> } catch (IOException e) {
>> if (r==-1 && e.getCause() instanceof
>> ChannelClosedException) {
>> // JENKINS-5073
>> // r==-1 only when the execution of the command
>> resulted in IOException,
>> // and we've already reported that error. A common
>> error there is channel
>> // losing a connection, and in that case we don't
>> want to confuse users
>> // by reporting the 2nd problem. Technically the 1st
>> exception may not be
>> // a channel closed error, but that's rare enough,
>> and JENKINS-5073 is common enough
>> // that this suppressing of the error would be
>> justified
>> LOGGER.log(Level.FINE, "Script deletion failed", e);
>> } else {
>> Util.displayIOException(e,listener);
>> e.printStackTrace(
>> listener.fatalError(Messages.CommandInterpreter_UnableToDelete(script)) );
>> }
>> } catch (Exception e) {
>> e.printStackTrace(
>> listener.fatalError(Messages.CommandInterpreter_UnableToDelete(script)) );
>> }
>> }
>> }
>>
>> /**
>> * Reports the exit code from the process.
>> *
>> * This allows subtypes to treat the exit code differently (for
>> example by treating non-zero exit code
>> * as if it's zero, or to set the status to {@link Result#UNSTABLE}).
>> Any non-zero exit code will cause
>> * the build step to fail. Use {@link
>> #isErrorlevelForUnstableBuild(int exitCode)} to redefine the default
>> * behaviour.
>> *
>> * @since 1.549
>> */
>> protected int join(Proc p) throws IOException, InterruptedException {
>> return p.join();
>> }
>>
>> /**
>> * Creates a script file in a temporary name in the specified
>> directory.
>> */
>> public FilePath createScriptFile(@Nonnull FilePath dir) throws
>> IOException, InterruptedException {
>> return dir.createTextTempFile("hudson", getFileExtension(),
>> getContents(), false);
>> }
>>
>> public abstract String[] buildCommandLine(FilePath script);
>>
>> protected abstract String getContents();
>>
>> protected abstract String getFileExtension();
>>
>> private static final Logger LOGGER =
>> Logger.getLogger(CommandInterpreter.class.getName());
>>
>> }
>>
>> On Wednesday, 16 November 2016 17:15:12 UTC+5:30, Robert Sandell wrote:
>>>
>>> Here are the classes involved in "execute script" step.
>>>
>>>
>>> https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/tasks/BatchFile.java
>>>
>>> https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/tasks/Shell.java
>>>
>>> https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/tasks/CommandInterpreter.java
>>>
>>> /B
>>>
>>>
>>> On Wed, Nov 16, 2016 at 8:41 AM, Kul Bhushan Srivastava <
>>> [email protected]> wrote:
>>>
>>>> If anyone can guide how the windows bactch command execution are
>>>> handled from backend JAVA API. Then I may create one of my own.
>>>>
>>>> On Monday, 14 November 2016 13:37:49 UTC+5:30, Kul Bhushan Srivastava
>>>> wrote:
>>>>>
>>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Jenkins Developers" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/jenkinsci-dev/76d6ddbf-14a2-405d-8197-f2dd549e8248%40googlegroups.com
>>>>
>>>> <https://groups.google.com/d/msgid/jenkinsci-dev/76d6ddbf-14a2-405d-8197-f2dd549e8248%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>>>
>>> --
>>> Robert Sandell
>>> *Software Engineer*
>>> *CloudBees Inc.*
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Jenkins Developers" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/jenkinsci-dev/39ff5e49-dcf3-4098-a505-de706522682e%40googlegroups.com
>>
>> <https://groups.google.com/d/msgid/jenkinsci-dev/39ff5e49-dcf3-4098-a505-de706522682e%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> Robert Sandell
> *Software Engineer*
> *CloudBees Inc.*
>
--
You received this message because you are subscribed to the Google Groups
"Jenkins Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/jenkinsci-dev/94ef1b9a-a8ee-441c-a524-88067a0fda20%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.