Saturday, May 10, 2014

Saiku Analytics : UI customization and deploy UI and webapp on different servers


Saiku Analytics, from Meteorite BI is built in a manner that is easy for developers to customize user interface. Its architecture has been designed for that : there is a backend J2EE webapp for Mondrian/OLAP/MDX and database queries stuff, and an UI webapp that uses the first one via REST/AJAX/JSON http queries.

If you still not have a working Saiku Server on your box, loose your necktie and follow the tutorial on this previous post.

I Assume for the following that you have approximatively the same installation than this described in my installation post : UI deployed as ROOT webapp and backend webapp as 'saiku' on Tomcat.

Saiku UI is based on backbone.js, underscore.js, and JQuery-template, but whitout diving into these frameworks we will see what we can do by few examples.

The html single page

Open file apache-tomcat-8.0.5/webapps/ROOT/index.html, and starting to line 144, there are scripts tag of type text/x-jquery-tmpl. Each of them is responsible for displaying one area of the UI.

These scripts block are jQuery-template code blocks, we will change them without thinking hard about
jQuery-template framework, finally this is just HTMl code with placeholders and conditionnal directives.

Top toolbar - modify and brand with your company logo.

the first JQuery-template script on line 141 displays the toolbar on top :

<script type="text/x-jquery-tmpl" id="template-toolbar">
    <ul>
            <li><a id='new_query' href='#new_query' title='New query' class='new_tab i18n sprite'></a></li>
            <li class='separator'>&nbsp;</li>
            <li><a id='open_query' href='#open_query' title='Open query' class='open_query i18n sprite'></a></li>
            <li class='separator'>&nbsp;</li>
            <li><a id='logout' href='#logout' title='Logout' class='logout i18n sprite'></a></li>
            <li><a id='about' href='#about' title='About' class='about i18n sprite'></a></li>
            <li class='separator'>&nbsp;</li>
            <li><a id='issue_tracker' href='#issue_tracker' title='Issue Tracker' class='bug i18n sprite'></a></li>
    </ul>
        <h1 id='logo'><a href='http://www.analytical-labs.com/' title='Saiku - Next Generation Open Source Analytics' class='sprite'>Saiku</a></h1>
</script>

Just comment/remove li tags to hide some buttons, and for changing the logo remove id=logo on h1 tag and class='sprite' on <a> tag, and replace it by your favorite company logo with an img tag.

Querying toolbar

In the same way query toolbar corresponds to jQuery-template script tag on line 298 with id id="template-workspace-toolbar".
Ok you have understood...

Internationalization - labels

All text labels are written in JSON files on apache-tomcat-8.0.5/webapps/ROOT/js/saiku/plugins/I18n/po. Find the one that corresponds to your language and fee free to modify with your jargon.
Language displayed in UI corresponds to one of the preferred languages set on your web browser.

Google analytics tracker modification

Still index.html, the block on line 626

<script type="text/javascript" src="js/ga.js"></script>
Calls ga.js that activate google analytics tracker of Meteorite BI. Change in ga.js account variable value with your GA account ID
Otherwise remove call to this script by commeting this line on index.html

Manage Authentication pop-in display, change default logins/passwords

Ok this subject merits a further consideration than a brief paragraph, but quickly two tips, before a forthcoming post about authentication/permissions in Saiku

Change default password

By default user are declared in a text file on Saiku backend webapp (not ui webapp)
To change default password, add user etc, open
apache-tomcat-8.0.5/webapps/saiku/WEB-INF/users.properties, it contains

#Username,password,role
bob=dylan,ROLE_USER
krishna=krish2341,ROLE_USER
smith=pravah@001,ROLE_USER
admin=admin,ROLE_USER,ROLE_ADMIN

So syntax is :
[login]=[password],[roles....]

Add lines, change password etc.

Remove authentication pop-in.

For demonstration, POC, tests, you should need to remove authentication popin, and be always and directly logged as admin.

Open apache-tomcat-8.0.5/webapps/ROOT/js/saiku/Settings.js
And you will see one lines 139 to 142

if (window.location.hostname && (window.location.hostname == "dev.analytical-labs.com" || window.location.hostname == "demo.analytical-labs.com" )) {
    Settings.USERNAME = "admin";
    Settings.PASSWORD = "admin";
}

Comment the "if" clause and its related closing bracket, reload the page, no authentication pop-in anymore.

Embed html page in an existing webapp, and deploy Saiku backend to another server - Run UI and webapp on different servers

A common use case, to take advantage of the two webapps architecture of Saiku, is to add the html page index.html and its related js/css stuff to an existing application/server (an enterprise portal, a php application etc), perform your personal make-up on it, and deploy Saiku backend saiku-webapp-2.5.war to another webapp. Let's see how to do this this stuff.

UI part

In apache-tomcat-8.0.5/webapps/ROOT/js/saiku/Settings.js
/**
 * Change settings here
 */
var Settings = {
    VERSION: "Saiku 2.5",
    BIPLUGIN: false,
    BASE_URL: "",
    TOMCAT_WEBAPP: "/saiku",
    REST_MOUNT_POINT: "/rest/saiku/",
    DIMENSION_PREFETCH: true,
    ERROR_LOGGING: false,
You see on line 23 :

BASE_URL:""

Complete this line to make point the whole UI to another URL, for instance http://localhost:8081
(For a quick test, just copy/paste  whole apache tomcat directory, change in apache-tomcat-8.0.5-copied/conf/server.xml, server shutdown port, line 22, to 8006, http connector port, line 68, to 8081 and ajp connector port, line 90, to 8010).

Ok It's good but your first test on a browser fails, and your browser debug console says that 'Cross origin requests are only supported for HTTP'.

It's about same origin policy

We will not dive into this subject here, and only avoid this snap.
A mandatory trick is to enable ajax calls from the UI to ship authentication cookie sent by webapp during authentication stage :

Open apache-tomcat-8.0.5/webapps/ROOT/js/saiku/adapters/SaikuServer.js

and add line 145 to ajax parameters this parameter :
xhrFields: {withCredentials: true}

In order to have
    params = {
      url:          url,
      type:         type,
      cache:        false,
      data:         data,
      contentType:  contentType,
      dataType:     dataType,
      success:      success,
      statusCode:   statuscode,
      error:        failure,
      async:        async,
      xhrFields: {
                withCredentials: true
          }

Saiku webapp part

Apache Tomcat API provides a CORS Filter that removes this limitation (CORS for Cross-Origin Resource Sharing, see http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter for this filter, and http://manning.com/hossain/CORSinActionCH01.pdf, first chapter is free to read,see what is behind CORS).
So open (on the tomcat that hosts the webapp, not the UI) apache-tomcat-8.0.5-copied/webapps/saiku/WEB-INF/web.xml, and paste on line 15 following snippet :
  <filter>
     <filter-name>CorsFilter</filter-name>
     <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  </filter>
  <filter-mapping>
       <filter-name>CorsFilter</filter-name>
       <url-pattern>/*</url-pattern>
  </filter-mapping>

Now this server can respond to ajax queries from another host (to sum-up).

6 comments:

  1. Hi,
    I have a question:
    - how can i save query in the database instead of putting it in the directory saiku-repository

    - Is it possible to read the contents of datasource files from DB instead of the directory saiku-source

    For information: i use saiku 2.5 CE

    Thanks

    ReplyDelete
  2. How you can initially display a query in saiki 3.6.3?. Before modifying the file to Setting.js INITIAL_QUERY to true.

    ReplyDelete
  3. hello i want that spagobi pass parameter(login and password) to saiku
    and remove the saiku authentication can you help me
    thank you :)

    ReplyDelete
  4. Youn can use js function like this:

    function loginSession(){
    var xhr = getXMLHttpRequest();
    xhr.open("POST", "/saiku/rest/saiku/session/", true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send("username=USER&password=PASSWORD");
    }

    function logoutSession(){
    var xhr = getXMLHttpRequest();
    xhr.open("DELETE", "/saiku/rest/saiku/session/", true);
    xhr.send(null);
    }

    ReplyDelete
  5. Hi, i neeed to saiku iu running with two sepparated database conection. Is his possible? ie
    localhost:8080/cube
    localhost:8080/cube2

    Every app conected to another database each with hes own sales.txt file. is possible?

    ReplyDelete