Hi everyone,
I'm currently implementing a plugin that creates jobs and fills them with build
steps.
I have a dropdown list for the different project types, and a repeatable field
with dropboxes for the build steps available to the selected project.
Here's the jelly:
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
xmlns:l="/lib/layout" xmlns:t="/lib/hudson"
xmlns:f="/lib/form">
<f:entry title="Projectname" field="${projectName}">
<f:textbox />
</f:entry>
<f:entry title="Build project after creation?"
field="runProjectAfterCreation">
<f:checkbox />
</f:entry>
<f:entry field="projectType" title="Project / Job Type">
<f:select default="noTypeSelected" />
</f:entry>
<f:entry title="Build Steps">
<f:repeatable var="buildSteps" items="${instance.buildSteps}" minimum="1">
<table width="100%" bgcolor="#EEEEEE">
<div width="100%">
<f:entry field="BuildStepType">
<f:select default="noBuildStepSelected" />
<f:repeatableDeleteButton value="Delete Build Step" />
</f:entry>
</div>
</table>
</f:repeatable>
</f:entry>
</j:jelly>
And here's the java code of the plugin (Left some unrelated code out...):
public class JobCreator extends Builder {
private final String projectName;
private final String projectType;
private final boolean runProjectAfterCreation;
private final List<String> buildSteps;
// Fields in config.jelly must match the parameter names in the
"DataBoundConstructor"
@DataBoundConstructor
public JobCreator( final String projectName, final boolean
runProjectAfterCreation, final String projectType,
final List<String> buildSteps ) {
this.projectName = projectName;
this.runProjectAfterCreation = runProjectAfterCreation;
this.projectType = projectType;
this.buildSteps = buildSteps;
}
public String getJobName() // ...
public boolean getRunJobAfterCreation() // ...
public String getProjectType() // ...
public List<String> getBuildSteps() // ...
@Override
public boolean perform( final AbstractBuild<?, ?> build, final Launcher
launcher, final BuildListener listener )
throws AbortException {
// ...
}
private void runProject( final AbstractProject<?, ?> project ) {
// ...
}
// Overridden for better type safety.
// If your plugin doesn't really define any property on Descriptor,
// you don't have to do this.
@Override
public Descriptor getDescriptor() {
return (Descriptor) super.getDescriptor();
}
@Extension
public static final class Descriptor extends BuildStepDescriptor<Builder> {
public Descriptor() {
load();
}
public FormValidation doCheckJobName( @QueryParameter final String
value ) throws IOException, ServletException {
// ...
}
// Is overridden, so we have to use the raw type
@SuppressWarnings( "rawtypes" )
@Override
public boolean isApplicable( final Class<? extends AbstractProject>
aClass ) {
// Indicates that this builder can be used with all kinds of
project types
return true;
}
@Override
public String getDisplayName() {
return "Create new Job";
}
public ListBoxModel doFillProjectTypeItems() {
ListBoxModel items = new ListBoxModel();
items.add( "Bitte Projekttyp wählen", "noTypeSelected" );
for ( TopLevelItemDescriptor tliDescriptor : getAvailableJobTypes()
) {
items.add( tliDescriptor.getDisplayName(),
tliDescriptor.getId() );
}
return items;
}
/**
* Fills the dropbox "buildStepType" with the available build steps
*/
@SuppressWarnings( "unchecked" )
public ListBoxModel doFillBuildStepTypeItems( @QueryParameter final
String projectType ) {
ListBoxModel items = new ListBoxModel();
// THROWS A NULL POINTER EXCEPTION IN THIS IF BLOCK
if ( ( !projectType.equals( "noTypeSelected" ) ) && (
!projectType.equals( "hudson.maven.MavenModuleSet" ) ) ) {
try {
for ( BuildStepDescriptor<? extends Builder> buildStep :
getAvailableBuilders( (Class<? extends AbstractProject<?, ?>>) Class
.forName( projectType ).asSubclass(
AbstractProject.class ) ) ) {
items.add( buildStep.getDisplayName(),
buildStep.getId() );
}
} catch ( ClassNotFoundException ex ) {
throw new RuntimeException( ex );
}
// Maven projects will throw a java.lang.ClassNotFoundException
} else if ( projectType.equals( "hudson.maven.MavenModuleSet" ) ) {
items.add( "Mavenprojekte werden nicht unterstützt!",
"mavenSelected" );
} else {
items.add( "Bitte erst Projekttyp wählen!", "noProjectType" );
}
return items;
}
private List<BuildStepDescriptor<? extends Builder>>
getAvailableBuilders(
final Class<? extends AbstractProject<?, ?>> projectType ) {
List<BuildStepDescriptor<? extends Builder>> builders = new
ArrayList<BuildStepDescriptor<? extends Builder>>();
// Add all build steps which are applicable to the project type and
which have a DataBoundConstructor to the
// list
for ( hudson.model.Descriptor<Builder> descriptor : Builder.all() )
{
if ( !( descriptor instanceof BuildStepDescriptor ) ) {
continue;
}
BuildStepDescriptor<? extends Builder> buildStepDescriptor =
(BuildStepDescriptor<? extends Builder>) descriptor;
if ( buildStepDescriptor.isApplicable( projectType ) && hasDbc(
buildStepDescriptor.clazz ) ) {
builders.add( buildStepDescriptor );
}
}
return builders;
}
private List<TopLevelItemDescriptor> getAvailableJobTypes() {
List<TopLevelItemDescriptor> tlis = new
ArrayList<TopLevelItemDescriptor>();
for ( TopLevelItemDescriptor tliDescriptor : Items.all() ) {
tlis.add( tliDescriptor );
}
return tlis;
}
private boolean hasDbc( final Class<?> clazz ) {
for ( Constructor<?> constructor : clazz.getConstructors() ) {
if ( constructor.isAnnotationPresent(
DataBoundConstructor.class ) ) {
return true;
}
}
return false;
}
@Override
public boolean configure( final StaplerRequest req, final JSONObject
formData ) throws FormException {
save();
return super.configure( req, formData );
}
}
}
If you need additional code (I commented/left some lines out), please tell me
so.
Jenkins throws a java.lang.reflect.InvocationTargetException caused by a
java.lang.NullPointerException at line 218
(JobCreator$Descriptor.doFillBuildStepTypeItems, I marked it in the code
excerpt)
Debugging the method shows that the QueryParameter projectType is null. The
method also isn't called when I select a value from the project type dropdown
list.
Can somebody help me with this?
Thanks in advance,
Sebastian
--
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].
For more options, visit https://groups.google.com/d/optout.