Creating your own Parameter UI for the Pentaho BI-Server

Our BI-Server ships with a default GWT parameter UI for the parameter defined on a report. If you had been around for a while, then you will remember the sigh of relieve when we freed everyone from the tyranny of XActions for running simple reports. Since then the parameter capabilities of the reporting module grew and grew with every release making these parameters easier to use than the XActions’s original design.

GWT is nice for a old and grumpy Java developer like me, as I do not have to worry about JavaScript (untyped, for heaven’s sake, untyped!). But the hardcore nerds like Pedro “JavaScript is my life” Alves do not like the monolithic garbage the GWT compiler spits out. To slow, to heavy, and foremost: Not really extensible unless you recompile the beast for each change. And worst of all: I agree to these complaints.

However, there is a silver lining on the horizon. Our architecture is open, so you are able to replace the GWT code with your own magic with no problems at all. And here is how you would do it:

Basics: The parameter UI architecture

The parameter UI works as a REST service. The server receives calls and sends responses based on the parameters given, without holding any server side state elsewhere.

(1) The browser loads the report.html page and initializes the GWT parameter application (GWT from now on).

(2) GWT calls the server’s report handler with “renderMode=PARAMETER” or “renderMode=XML”. If there are values for any of the parameters known, then these values are given on the URL using ordinary HTTP-GET or POST requests.

The URL that is called is something like this:

http://demo.pentaho.com/pentaho/content/reporting?renderMode=XML&solution=steel-wheels&path=%2Freports&name=Product+Sales.prpt

(3) The server responds with the parameter XML document. If the renderMode is XML, this document also contains the number of pages in the report. The server only returns page numbers if the parameter validate correctly and if the pagination does not cause any other errors.

(If you are logged into the demo server, call the URL from step 2 in your browser to see the XML document the server returns.)

(4) GWT creates a UI for all parameters based on the Parameter XML document. All information is given as attributes on the parameter. The parameter’s possible values and current value are given in that document as well. These sets of values can change if a other parameter changes.

(5) If all parameters validated correctly (according to the Parameter XML document), it now sends a request to retrieve the rendered report. Again, this is a ordinary HTTP-GET call with all parameters attached onto the URL.

http://demo.pentaho.com/pentaho/content/reporting?renderMode=REPORT&solution=steel-wheels&path=%2Freports&name=Product+Sales.prpt

(6) The Browser displays the report content in the IFrame below the GWT parameter UI.

(7) Paging through the report jumps back to step (6) and updates the report frame.

(8) Changing a parameter value jumps back to step (2) and updates the parameter information.

The mystical Parameter XML

The parameter XML document is a description of all known parameters that the reporting plugin understands. The same format is also used by the Analyzer component and you can even get parameter information in this format out of XActions.

<?xml version="1.0" encoding="UTF-8"?>
  <parameters accepted-page="-1" autoSubmitUI="true" is-prompt-needed="false" layout="vertical" page-count="1" paginate="true" subscribe="false">
    <parameter is-list="true" is-mandatory="false" is-multi-select="false" is-strict="true" name="PROD_LINE" type="java.lang.String">
      <attribute name="role" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="user"/>
      <attribute name="parameter-layout" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="horizontal"/>
      <attribute name="parameter-render-type" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="togglebutton"/>
      <attribute name="label" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="Line"/>
      <attribute name="mandatory" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="true"/>
      <values>
        <value label="Classic Cars" null="false" selected="true" type="java.lang.String" value="Classic Cars"/>
        <value label="Motorcycles" null="false" selected="false" type="java.lang.String" value="Motorcycles"/>
        <value label="Ships" null="false" selected="false" type="java.lang.String" value="Ships"/>
        <value label="Planes" null="false" selected="false" type="java.lang.String" value="Planes"/>
      </values>
    </parameter>
    <parameter is-list="true" is-mandatory="false" is-multi-select="false" is-strict="true" name="PROD_CODE" type="java.lang.String">
      <attribute name="role" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="user"/>
      <attribute name="parameter-visible-items" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="6"/>
      <attribute name="parameter-render-type" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="list"/>
      <attribute name="label" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="Product"/>
      <attribute name="mandatory" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="true"/>
      <values>
        <value label="1952 Alpine Renault 1300" null="false" selected="true" type="java.lang.String" value="S10_1949"/>
        <value label="1972 Alfa Romeo GTA" null="false" selected="false" type="java.lang.String" value="S10_4757"/>
        <value label="1962 LanciaA Delta 16V" null="false" selected="false" type="java.lang.String" value="S10_4962"/>
        <!-- loads of parameter values removed -->
        <value label="1961 Chevrolet Impala" null="false" selected="false" type="java.lang.String" value="S24_4620"/>
        <value label="1982 Camaro Z28" null="false" selected="false" type="java.lang.String" value="S700_2824"/>
      </values>
    </parameter>
    <parameter is-list="true" is-mandatory="true" is-multi-select="false" is-strict="true" name="output-target" type="java.lang.String">
      <attribute name="role" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="system"/>
      <attribute name="preferred" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="true"/>
      <attribute name="parameter-group" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="parameters"/>
      <attribute name="parameter-group-label" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="Report Parameters"/>
      <attribute name="label" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="Output Type"/>
      <attribute name="parameter-render-type" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="dropdown"/>
      <attribute name="hidden" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="false"/>
      <values>
       <value label="HTML (Paginated)" null="false" selected="true" type="java.lang.String" value="table/html;page-mode=page"/>
       <value label="HTML (Single Page)" null="false" selected="false" type="java.lang.String" value="table/html;page-mode=stream"/>
       <value label="PDF" null="false" selected="false" type="java.lang.String" value="pageable/pdf"/>
       <value label="Excel" null="false" selected="false" type="java.lang.String" value="table/excel;page-mode=flow"/>
       <value label="Excel 2007" null="false" selected="false" type="java.lang.String" value="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;page-mode=flow"/> 
       <value label="Comma Separated Value" null="false" selected="false" type="java.lang.String" value="table/csv;page-mode=stream"/> 
       <value label="Rich-Text-Format" null="false" selected="false" type="java.lang.String" value="table/rtf;page-mode=flow"/>
       <value label="Text" null="false" selected="false" type="java.lang.String" value="pageable/text"/>
     </values>
   </parameter>
   <!-- many many more parameter -->
 </parameters>

To create a usable UI, you need to look at some critical information in the parameter UI.

The parameter element itself contain the most critical information for a parameter.

<parameter is-list="true" is-mandatory="true" is-multi-select="false" is-strict="true" name="output-target" type="java.lang.String">

The parameter name gives the parameters internal name. Usually each parameter also has a “label” defined as attribute. The “label” is shown to the user, the “name” is sent to the server. The parameter element also indicates whether a parameter is a list or plain parameter. List parameter have a predefined list of values from which the user can choose from. Some list parameter allow the user to select multiple values (“is-multi-select”) or control whether the user can specify additional values (“is-strict”) or whether the parameter can be empty (“is-mandatory”). You can use this to perform client-side validity checks if you want to. But no matter what you do, the server checks the input anyway, as client side input is untrusted input. Not all parameter that are listed in the parameter document are shown to the user. Some are system level parameter that are only useful in certain situations (like all subscription parameter). A parameter is hidden if the hidden attribute is set to true.

 <attribute name="hidden" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="false"/>

How a parameter is presented to the user is defined by the “parameter-render-type”. Right now, this attribute can have the following values:

  • dropdown
  • list
  • radio
  • checkbox
  • togglebutton
  • textbox
  • datepicker
  • multi-line
 <attribute name="parameter-render-type" namespace="http://reporting.pentaho.org/namespaces/engine/parameter-attributes/core" value="dropdown"/>

Data formats for sending and receiving data

Sending parameter information over the internet can be a funny exercise. HTTP only allows to send text, so objects like dates and numbers need to be encoded properly. The Pentaho Reporting plugin expects all parameters in a locale-independent standard format. Numbers must be encoded as decimal numbers in plain english format (point as decimal separator, no thousands separators) using the format string “#0.#########”. Dates and Times must be given in the standard ISO format using the format string “yyyy-MM-dd’T’HH:mm:ss.SSS” or (if encoded with timezone information “yyyy-MM-dd’T’HH:mm:ss.SSSZZZZ”). (Also see: “Its about time – better Date parameter handling in Pentaho Report Designer“) Multi-selection parameter must be given by repeating the parameter name for each value. The order of multi-selection values is taken into account when processing the parameters on the server side. Example:

../report?multi-select=Value1&multi-select=Value2

Now all we need is a bit of JavaScript magic on the client side to replace the grumpy old GWT parameter application with a lightweight and smooth pure JavaScript/AJAX solution. Stay tuned ..

Additional Reading Material

This entry was posted in Advanced Topic, BI-Server, Parameter, Tech-Tips on by .
Thomas

About Thomas

After working as all-hands guy and lead developer on Pentaho Reporting for over an decade, I have learned a thing or two about report generation, layouting and general BI practices. I have witnessed the remarkable growth of Pentaho Reporting from a small niche product to a enterprise class Business Intelligence product. This blog documents my own perspective on Pentaho Reporting's development process and our our steps towards upcoming releases.

13 thoughts on “Creating your own Parameter UI for the Pentaho BI-Server

  1. Andy Grohe

    I am very excited to see this and I can’t wait for the stay tuned part…..

    As you know I would be happy to help out here.

  2. Jonas Björk

    Hi,

    I checked out the Pentaho-Wiki already, but thanks for the link. I realized that it’s userid and password, but it still does not work. I am not accessing them from a browser but from a Java application. I also tried Basic Authentication both from java and with “wget –header=’Authorization: Basic [BASE64]’ –output-document=’out.xml’ http://localhost:8080/pentaho/content/reporting?renderMode=PARAMETER&solution…” and the authentication seems to work since I get a 200 OK but the content of out.xml is only “java.lang.NullPointerException” even though the exact same link works in a browser if I am already logged in. Any ideas?

  3. Thomas Morgner

    In that case do what we do in PRD:

    (1) Grab the apache-http-client.
    (2) Initialize your client with:

    final HttpClient client = new HttpClient();
    client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
    client.getParams().setSoTimeout(WorkspaceSettings.getInstance().getConnectionTimeout() * 1000);
    client.getParams().setAuthenticationPreemptive(true);
    client.getState().setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials(user, password));

    The important part is the “setAuthenticationPreemptive”.
    If you do not do that, you will be rerouted to the login page and when you
    will never get your data back.

  4. Thomas Morgner

    To see it in a working example:
    http://source.pentaho.org/viewvc/pentaho-reporting/tools/report-designer/tags/3.8.3-GA/report-designer-extension-pentaho/source/org/pentaho/reporting/designer/extensions/pentaho/repository/util/PublishUtil.java?view=markup

    We use the “openReport” method to communicate with the server to download the prpt file. Replace the “renderMode=DOWNLOAD” with “renderMode=XML” and you have your code.

    To be sure that you do not get redirected, set

    final GetMethod method = new GetMethod(paramServiceText);
    method.setFollowRedirects(false);

    on your HTTP-method. This way, if your login is not correct, you will receive a 302 error code from the server.

  5. Jonas Björk

    I am stuck with Apache Http Client 4 and with the help from your example I managed to get it to work using the following

    HttpHost targetHost = new HttpHost(“localhost”, 80, “http”);
    DefaultHttpClient httpclient = new DefaultHttpClient();
    httpclient.addRequestInterceptor(preemptiveAuth, 0);
    httpclient.getCredentialsProvider().setCredentials(
    new AuthScope(targetHost.getHostName(), targetHost.getPort()),
    new UsernamePasswordCredentials(user, pass));

    where the preemptiveAuth is

    HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() {
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
    AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
    CredentialsProvider credsProvider = (CredentialsProvider) context
    .getAttribute(ClientContext.CREDS_PROVIDER);
    HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);

    if (authState.getAuthScheme() == null) {
    AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
    Credentials creds = credsProvider.getCredentials(authScope);
    if (creds != null) {
    authState.setAuthScheme(new BasicScheme());
    authState.setCredentials(creds);
    }
    }
    }
    };

    Thanks again for your help.

  6. Utkarsh

    Hi,

    How can we handle the situation where we have cascading drop downs? How can we know about the dependent parameters?

    Thanks,
    Utkarsh

  7. Cuanq Gigabyte

    Hi,

    I do really interested with your blog and I am a newbie in Pentaho BI Server…

    I am now using Pentaho Community Server 5.2. I want to create a report with a horizontal view for my parameters but I’m stuck with it. I can’t make the parameters looks horizontal. It’s always viewed with a vertical layout. Please give me your kind solution for my problems…

    I already set the preferences in pentaho report designer to make the layout viewed horizontal too. But everything I tried is useless…

    I hope you don’t mind to give me your kind reply as soon as possible…

    Thank you…

  8. José Gil Ceballo

    Hi, I am working on a BI server plugin and define a SimpleAction class which implements the same Interfaces that SimpleReportingAction does. And publish some other bean properties which I planned to use as param inputs but I don’t know how to get the scheduler show the params.
    Can you give me a hint?
    Thank you so much.

  9. ThomasThomas Post author

    Start your journey by having a look at the “org.pentaho.platform.scheduler2.quartz.ActionAdapterQuartzJob” class. This is where the scheduler does all its work.

    Your action needs a default constructor, so that the class.newInstance() call works. The scheduler sets parameter as bean-properties (public getter/setter), or via the IVarArgsInterface (in case you cant predict what parameters may exist on your content).

    To create a job, the platform uses the IScheduler interface. The implementation of that is the Quartz-Scheduler. You can either get to this class via code by using “PentahoSystem” (a spring-xml lookup) and call the “scheduleJob” method directly, or via a REST call, which ends up in “SchedulerService” (called via “SchedulerResource”, which is a standard JAX-RS service implementation).

    All classses quoted are part of the pentaho-platform project.

    The mantle-UI also has some helper classes for giving you a scheduler dialog. To schedule content, you need to have a “parameterUi” handler for the content (see reporting/plugin.xml for an example). That handler should be a HTML page that contains your UI. The scheduler dialog then uses a few (undocumented) tricks to query the selected parameter set.

    See pentaho-gwt-widgets project and in there the “ScheduleParamsDialog” and “ScheduleParamsWizardPanel” class for the gory details.

  10. José Gil Ceballo

    Hello, I found the following aspects:
    – The parameterUi content generator must be present in plugin.spring.xml to ensure that the action is parameterizable.
    – The parameterUi content generator must provide the correct html content to present the parameter input elements along two global javascript variables:

    var initSchedulingParams = function(filePath, validParamsCallback){…}
    var getParams = function() {…; return paramsJson;}

    The first is used to initialize the validParamsCallback function which must be invoked passing a boolean in order to show when the parameters entry elements are ready fo input. If true the OK wizard button is enabled.
    The second is used to collect the parameter-values to be returned in the json form {param1-name:param1-value, …,paramN-name:paramN-value}

    The action bean properties like “setOutputType” must be reference by html/javascript param “output-type” for instance.

    That’s all the pieces of the puzzle.

    Thank you for your clues.
    best regards.

Comments are closed.