RuleSource design for repeatedly issuing JavaExec on model space elements

I’d like to be able to define a model space using a shared build script like so:

apply from: '../common/gradle/items.gradle'

model {
   items {
      item1(Item) {
         outputDirectory = file('../item1-out')
      item2(Item) {
         outputDirectory = file('../item2-out')

…and then be able to run a single task which has the effect of executing the same JavaExec task on each of the configured items, substituting the values of outputDirectory defined in each item in each execution of JavaExec.

I’m running into 2 problems:

  1. I’m getting this exception when gradle encounters the item1 declaration:
> Exception thrown while executing model rule: items{ ... } @ build.gradle line 14, column 5
   > Attempt to read a write only view of model of type 'java.lang.Object' given to rule 'items { ... } @ build.gradle line 14, column 5'
  1. I do not know how to create a single task that repeatedly runs JavaExec using the parameters defined in each configured Item. What is the best way to accomplish this? Should I create multiple different tasks for each configured item then create an empty task that uses finalizedBy to get all the other tasks to run? If so, what does that look like in the ItemRules class?

Here is the shared build script so far:

interface Item {
  void setOutputDirectory(File directory)
  File getOutputDirectory()


class ItemRules extends RuleSource {
  @Model void items(ModelMap<Item> theItemsMap) {
    println 'Configuring items'

  @Mutate void createExecTask(ModelMap<Task> tasks, ModelMap<Item> theItemsMap) {
     // what to do here?

apply plugin: ItemRules

Many thanks to Mark Vieira for sorting out the JavaExec problems (see thread below, if useful):

Now I’m trying to move these item rules out of the main build script and into an external shared build script, but I think doing so somehow changes the type name used to reference the Item elements, or is somehow affecting the ability of gradle to correctly interpret the configured Item elements.

The error message isn’t very helpful, though:

Attempt to read a write only view of model of type 'java.lang.Object' given to rule 'items { ... } @ build.gradle line 14, column 5'

…any suggestions welcome