Tuesday, March 12, 2013

Nested Data Sets with Input Parameters in BIRT

Update: Monday 23 June 2014, 12:58:32 PM - added missing documentation about Data Set Parameter Binding.

Earlier, I was having trouble with nested data sets in a BIRT report (Juno Service Release 1, BIRT 4.2.1)

I created a sample report where each row in the outer data set contained a list - the values for the inner data set. I was trying to use a Report Variable to hold that list and it wasn't working. You can see the code for that example in this pastebin post. It seems as though the outer data set is being completely evaluated before the inner data set - so that the inner data set is always left with the last value stored in the report variable.

The solution I found was to abandon report variables, and instead use Data Set Parameters whereby the outer data set will directly pass values to the inner data set. In this post, I will show how to do that.

Firstly, here is the complete source for the working report using Data Set Parameters to pass data from the outer data set to the inner: http://pastebin.com/3ehAahDj. It is a completely self contained example: the data is set up in the Scripted Data Set portion.

Next, here are instructions on how to set up data set parameters.

  1. In the Outer Data Set, create a column to represent the data that you will send to the Inner Data Set.
    1. Right click on the Outer Data Set and select Edit. It doesn't matter if the Outer Data Set will not directly use this data. In this situation, the Outer Data Set will not display this data - just pass it to the Inner Data Set.
    2. Click on Output Columns.
    3. Click Add and give the column a name and data type. The column, valuesForInner, is a Java Object in this case because it will be a list of values (java.util.ArrayList).
      Create Output Column in Outer Data Set for the data you will send to the Inner Data Set.
  2. In the Outer Data Set's fetch method, retrieve the data that you will send to the Inner Data Set.
    row["valuesForInner"] = value;
  3. In the Inner Data Set, create a parameter to represent the data being passed to it from the Outer Data Set.
    1. Right click on the Inner Data Set and select Edit.
    2. Click on Parameters.
    3. Click Add and give the parameter a name, data type and default value. The column, valuesFromOuter, is a Java Object (it will be a java.util.ArrayList) and its default value is null.
      Setting a parameter for the Inner Data Set - which will be passed to it from the Outer Data Set
  4. In the Inner Data Set, create a column to represent individual elements from data (a list) sent from the Outer Data Set through the parameter you just created.
    1. Right click on the Inner Data Set and select Edit.
    2. Click on Output Columns.
    3. Click Add and give the column a name and data type. The column, value, is a string - one element from the java.util.ArrayList input parameter above.
      Create Output Column in Inner Data Set for the data sent from the Outer Data Set.
  5. In the Inner Data Set's open method, retrieve the data from the parameter (which is a list - so I am getting an iterator() from it.
    values = inputParams["valuesFromOuter"].iterator();
  6. In the Inner Data Set's fetch method, populate the Output Column from list passed in through the input parameter.
    if (!values.hasNext() ) {
       return false;
    }
    row["value"] = values.next();
    return true;
          

Lastly, on the List that is making use of the Inner Data Set, go to the Property Editor, Binding tab and click on the "Data Set Parameter Binding" button.

When you click on the "Data Set Parameter Binding" button, make sure that it has a row binding the output column of your Outer Data Set to the correct Input Parameter of your Inner Data set for that usage of the List.

Here is the result. Pretty huh? :)

Preview of the report showing that data sent to the inner data set updates correctly

I asked about how to fix the original report in a few different places that you may find helpful when troubleshooting BIRT issues.