Jelly - Save repeatable elements in a list

1,594 views
Skip to first unread message

ThomasBrouwer

unread,
Aug 20, 2012, 9:20:53 AM8/20/12
to jenkin...@googlegroups.com
Hi there!

I'm trying to find the right code to store the inputs of a repeatable element into the same list. This is required because this is nested inside another repeatable element.

Currently my jelly code is:
      <f:repeatable field="categories" minimum="0">
        <table width="100%">
          <f:entry title="Category Name" field="categoryName">
            <f:textbox />
          </f:entry>
          
          <f:entry title="Labels">
          <f:repeatable field="allLabels" minimum="0">
          <table width="100%">
          <f:entry title="Label name" field="labelNames">
          <f:textbox />
          </f:entry>
          </table>
          <div align="right">
          <f:repeatableDeleteButton/>
        </div>
          </f:repeatable>
          </f:entry>
          
        </table>
        <div align="right">
          <f:repeatableDeleteButton/>
        </div>
      </f:repeatable> 

where the important bit is the labels fields.
The configure function in the DescriptorImpl class is:
        @Override
        public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
            req.bindJSON(this, formData);
            save();
            return true;
        }

and the info is stored in another class ThrottleCategory with constructor:
        @DataBoundConstructor
        public ThrottleCategory(String categoryName,
                                Integer maxConcurrentPerNode,
                                Integer maxConcurrentTotal,
                                List<String> allLabels) {
            this.maxConcurrentPerNode = maxConcurrentPerNode == null ? 0 : maxConcurrentPerNode;
            this.maxConcurrentTotal = maxConcurrentTotal == null ? 0 : maxConcurrentTotal;
            this.categoryName = categoryName;
            this.allLabels = allLabels;
        }

This all gives me an error suggesting the data from the list fields are in the wrong format or such:

Exception: java.lang.IllegalArgumentException: Failed to instantiate class hudson.plugins.throttleconcurrents.ThrottleJobProperty$ThrottleCategory from {"allLabels":[{"labelNames":"label_1"},{"labelNames":"label_2"}],"categoryName":"category_1"} 
Stacktrace:
javax.servlet.ServletException: java.lang.IllegalArgumentException: Failed to instantiate class hudson.plugins.throttleconcurrents.ThrottleJobProperty$ThrottleCategory from {"allLabels":[{"labelNames":"label_1"},{"labelNames":"label_2"}],"categoryName":"category_1"}
	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:616)
	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:659)
	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:488)
	at org.kohsuke.stapler.Stapler.service(Stapler.java:162)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:45)
	at winstone.ServletConfiguration.execute(ServletConfiguration.java:248)
	at winstone.RequestDispatcher.forward(RequestDispatcher.java:333)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:376)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:95)
	at hudson.plugins.greenballs.GreenBallFilter.doFilter(GreenBallFilter.java:58)
	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:98)
	at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:87)
	at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
	at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:47)
	at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
	at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
	at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:164)
	at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
	at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:50)
	at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
	at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:81)
	at winstone.FilterConfiguration.execute(FilterConfiguration.java:194)
	at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:366)
	at winstone.RequestDispatcher.forward(RequestDispatcher.java:331)
	at winstone.RequestHandlerThread.processRequest(RequestHandlerThread.java:215)
	at winstone.RequestHandlerThread.run(RequestHandlerThread.java:138)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.IllegalArgumentException: Failed to instantiate class hudson.plugins.throttleconcurrents.ThrottleJobProperty$ThrottleCategory from {"allLabels":[{"labelNames":"label_1"},{"labelNames":"label_2"}],"categoryName":"category_1"}
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:633)
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:669)
	at org.kohsuke.stapler.RequestImpl.bindJSON(RequestImpl.java:387)
	at hudson.plugins.throttleconcurrents.ThrottleJobProperty$DescriptorImpl.configure(ThrottleJobProperty.java:150)
	at jenkins.model.Jenkins.configureDescriptor(Jenkins.java:2686)
	at jenkins.model.Jenkins.doConfigSubmit(Jenkins.java:2649)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:288)
	at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:151)
	at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:90)
	at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:111)
	at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:53)
	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:574)
	... 37 more
Caused by: java.lang.IllegalArgumentException: Failed to convert the allLabels parameter of the constructor public hudson.plugins.throttleconcurrents.ThrottleJobProperty$ThrottleCategory(java.lang.String,java.lang.Integer,java.lang.Integer,java.util.List)
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:627)
	... 52 more
Caused by: java.lang.IllegalArgumentException: Failed to instantiate class java.lang.String from {"labelNames":"label_1"}
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:633)
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:678)
	at org.kohsuke.stapler.RequestImpl.bindJSON(RequestImpl.java:377)
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:625)
	... 52 more
Caused by: org.kohsuke.stapler.NoStaplerConstructorException: There's no @DataBoundConstructor on any constructor of class java.lang.String
	at org.kohsuke.stapler.RequestImpl.loadConstructorParamNames(RequestImpl.java:485)
	at org.kohsuke.stapler.RequestImpl.access$100(RequestImpl.java:76)
	at org.kohsuke.stapler.RequestImpl$TypePair.convertJSON(RequestImpl.java:612)
	... 55 more

What am I missing here/doing wrong?

Thank you!

ThomasBrouwer

unread,
Aug 20, 2012, 12:19:36 PM8/20/12
to jenkin...@googlegroups.com
Turns out the object belonging to allLabels was not automatically converted into an array or list of strings, but instead an array of JSONObjects. By adding this code I could convert it into an ArrayList<String>:

List<String> output = new ArrayList<String>();
       
for (JSONObject obj : json){
output.add(obj.getString(labelName));
ThrottleQueueTaskDispatcher.writeMessage("Yay! Has "+obj.getString(labelName));
}
       
return output;

However, something weird happens now: when I add three labels on the Jenkins configuration page, it remembers that I stored three of them, but when I then open the config page again, the three fields are left blank. Help?

ThomasBrouwer

unread,
Aug 20, 2012, 12:23:29 PM8/20/12
to jenkin...@googlegroups.com
On, and the strange this is that the data is stored inside my objects, they're just not put into those fields when going to the config page again...


On Monday, August 20, 2012 2:20:53 PM UTC+1, ThomasBrouwer wrote:

Zhengyuan Shen

unread,
Jun 12, 2013, 2:58:37 PM6/12/13
to jenkin...@googlegroups.com
Hi,

I am on the same stage as you are. Have you figured out a way to put into those fields when going to the config page again?

Thanks
Reply all
Reply to author
Forward
0 new messages