java - 如何在构建步骤的 config.jelly 中使用 optionalBlock

标签 java jenkins hudson jelly

我在创建构造函数时遇到问题,Jenkins 可以调用它来获取一些源自 Jelly 表单的 JSON 数据。为了测试,我用 mvn hpi:create 创建了一个最小的 Jenkins 插件以及以下两个自定义文件:

src/main/resources/foo/hyde/jenkins/plugins/OptionalBlockSampleBuilder/config.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:block>
    <table>
        <f:optionalBlock name="enableText" title="Enable optional text" checked="${instance.enableText}">
            <f:entry title="Optional text" field="text">
                <f:textbox />
            </f:entry>
        </f:optionalBlock>
    </table>
</f:block>

src/main/java/foo/hyde/jenkins/plugins/OptionalBlockSampleBuilder.java

package foo.hyde.jenkins.plugins;

public class OptionalBlockSampleBuilder extends hudson.tasks.Builder {

    public final String text;
    public final boolean enableText;

    @org.kohsuke.stapler.DataBoundConstructor
    public OptionalBlockSampleBuilder(String text, Boolean enableText) {
        this.text = text;
        this.enableText = (enableText != null) && enableText;
    }

    @Override
    public boolean perform(hudson.model.AbstractBuild build, hudson.Launcher launcher, hudson.model.BuildListener listener) {
        listener.getLogger().println("OptionalBlockSampleBuilder " + enableText + "/" + text);
        return true;
    }

    @hudson.Extension
    public static final class DescriptorImpl extends hudson.tasks.BuildStepDescriptor<hudson.tasks.Builder> {
        public boolean isApplicable(Class<? extends hudson.model.AbstractProject> aClass) {
            return true;
        }
        public String getDisplayName() {
            return "Optional Block Sample";
        }
    }
}

我正在针对 pom.xml 父级构建 <groupId>org.jenkins-ci.plugins</groupId><artifactId>plugin</artifactId><version>1.454</version> ,并且一切都构建好了,Netbeans 6.9.1 启动了 Debug Jenkins,我开始使用这个构建步骤创建一个作业。如果我不选中该复选框,一切正常,我得到了预期 OptionalBlockSampleBuilder false/null到作业的控制台输出。

但是如果我确实选中复选框并添加文本,那么保存/应用作业配置会在 Jenkins 代码的深处给出这个异常,当它试图调用我的构造函数时:

java.lang.RuntimeException:
  Failed to instantiate class
    foo.hyde.jenkins.plugins.OptionalBlockSampleBuilder 
  from {
    "enableText":{"text":"xx"},
    "kind":"foo.hyde.jenkins.plugins.OptionalBlockSampleBuilder",
    "stapler-class":"foo.hyde.jenkins.plugins.OptionalBlockSampleBuilder"
    }

必须有一个简单的修复方法。我尝试了许多不同的更改,也尝试查看其他插件如何使用它,最终创建了这个最小的测试插件。如何修复它以使 optionalBlock 工作?

最佳答案

提示来自JSON数据:

{
"enableText":{"text":"xx"},
"kind":"foo.hyde.jenkins.plugins.OptionalBlockSampleBuilder",
"stapler-class":"foo.hyde.jenkins.plugins.OptionalBlockSampleBuilder"
}

你可以在这里看到 enableText 包含一个子属性,text。这意味着 f:optionalBlock实际上是期望对 block 中包含的所有字段进行封装——检查 block 时,您将收到封装字段类的实例;取消选中时,该字段将为 null。要正确使用 optionalBlock,您需要 @DataBoundConstructor 接受一个封装整个 optionalBlock 的可空类实例。例如:

private String text;

@DataBoundConstructor
public MyClass(EnableTextBlock enableText)
{
    if (enableText != null)
    {
        this.text = enableText.text;
    }
}

public static class EnableTextBlock
{
    private String text;

    @DataBoundConstructor
    public EnableTextBlock(String text)
    {
        this.text = text;
    }
}

请注意,本例中的 enableText 字段实际上是 EnableTextBlock 类的一个实例,它包含一个子属性 text。这将满足以表单形式发送的 JSON 对象。


相反,如果您只需要一个具有复选框以启用该字段输入的字段,您可能需要考虑使用 f:optionalProperty标签,它将为您处理单字段封装。然而,在许多情况下,optionalBlock 实际上需要配置多个字段,在这种情况下,封装类(如上示例)通常是正确的方法。

封装类不一定是静态内部类;它可以是您的包中的一个单独的类,但重要的部分是 DataBoundConstructor 应该接受一个与从表单传递的 JSON 结构相匹配的参数。

关于java - 如何在构建步骤的 config.jelly 中使用 optionalBlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13024929/

相关文章:

svn - Hudson 可以配置为构建每个修订版吗?

Docker 挂载卷 GID 不匹配导致错误 : dial unix/var/run/docker. sock: connect: permission denied

django - 如何为 Django 应用程序编写 Groovy Jenkinsfile 来运行我的测试?

java - src 的 findbugs 命令行

continuous-integration - 我如何知道 Jenkins 当前项目的内部版本号?

android - 尝试升级到最新的 Gradle (2.2.0) 时构建失败

java - 当值为 null 时,Log4j 打印 json 键名

java - 当我想加载 ListView 时,Android ArrayAdapter 崩溃

java - jetty 6 : Cannot create context (NoInitialContextException)

java - 哪个选择器最适合 Appium 测试不同版本的设备?