Oracle EPM 11.1.1.3 – Hyperion Shared Services integration with external Applications – Java API – Part 1 - Introduction

One of the major enhancements that came in the Hyperion EPM 11 release is the availability of Java APIs to access shared services from external applications. In the prior releases, SDK’s were available but those have been enhanced completely now in this release to accommodate new features. Also with the plans of opening up Essbase in the form of Web Services through a WSDL in future releases, makes the Java API option a definitive plus from an integration standpoint. In fact one can find traces of the WSDL implementation in the 11 release itself (if you browse through the complete installation directories). So theoretically opening up shared services and other applications through Java API means one has more control on import and export of users/groups into shared services.

Shared Services currently does not support table authentication whereas BI EE does. So, one common issue that people faced while using EPM and BI EE together in prior releases(pre-9.3) is in migrating the users from a database table to shared services. The only way then was to use an export/import utility shipped with shared services that accepted a CSV or an XML file for the import process. So, the database table would have to be exported into a CSV in a specific format (which in itself was not documented well) and then imported back to shared services using the import utility. But now with the advent of Java APIs it has become easier to manage the export import process. In addition, this opens up a lot of integration opportunities revolving around using shared services as a federating user directory.

Today we shall see what pre-requisites are needed to get this working. Unfortunately, the documentation falls short in explaining all the bits and pieces. Following are the components you will need

  1. Hyperion Shared Services 11.1.1.1 client archive (or fully installed shared services)
  2. JDeveloper or any Java IDE/client

One of the first things that you would notice is the fact that JAPIs of Hyperion are completely different(due to a different implementation methodology probably) from any other Oracle’s own native product like BI Publisher etc. Looking at the API you can clearly understand why it was not documented before (you can find a lot of jar files used extensively, interchangeably by a lot of Hyperion Components) as there are still quite a lot of jar files you would need to get it to work. Unfortunately the documentation just points to the fact that you would need the class path to be qualified correctly without mentioning where or what those jar files are.

To start with i would be using the sample.java file that comes with the EPM documentation. For the sake of clarity i have provided the code for this java file below.

package hsssecurity;

import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;

import com.hyperion.css.CSSAPIIF;
import com.hyperion.css.CSSDirectoryManagementAPIIF;
import com.hyperion.css.CSSException;
import com.hyperion.css.CSSSystem;
import com.hyperion.css.CSSUserProvisioningAPIIF;
import com.hyperion.css.common.CSSGroupIF;
import com.hyperion.css.common.CSSPrincipalIF;
import com.hyperion.css.common.CSSRoleIF;
import com.hyperion.css.common.CSSUserIF;

public abstract class hsssecurity {
	 // Handle to Instance of CSS System
    protected CSSSystem system = null;
    // Handle to Instance of CSSAPI
	protected CSSAPIIF cssAPI = null;
	//Handle to Directory management API
	protected CSSDirectoryManagementAPIIF cssDMAPI;
	//Handle to User Provisioning API
	protected CSSUserProvisioningAPIIF cssUPAPI;
	//the identity of the entity performing the operation.
	protected CSSPrincipalIF principal = null;

	protected HashMap context;

	public static String PRODUCT = "HUB-9.5.0";

	public hsssecurity() {
		initialize();
	}

   /**
    * Initialize the CSS Framework
    */
    private void initialize()
    {
        try
        {
        	System.out.println("Initializing CSS ...");
        	context = new HashMap();

            // Get Instance of the CSS System. Specify the location of
            // the Shared Services Client log file.
            // CSS will be intialized from configuration stored in Registry.
             System.out.println("Initializing CSS ...");
            system = CSSSystem.getInstance(context, "C:/Oracle/Hyperion/logs");
            System.out.println("Initialized CSS.");

            // get Handle the CSS API Interface
            cssAPI = system.getCSSAPI();

            cssDMAPI = cssAPI.getDirectoryManagementAPI(new HashMap());

            cssUPAPI = cssAPI.getUserProvisioningAPI(new HashMap());

            System.out.println("Getting the Principal ...");
            principal = getPrincipal();
            System.out.println("Got Principal.\n");

            context = new HashMap();
        }
        catch (Exception ce)
        {
            ce.printStackTrace();
        }
    }

	/**
	 * Shuts down the CSS framework.
	 */
    public void shutdown() {
    	try {
    		system.shutdown();
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

      private CSSPrincipalIF getPrincipal() {
    	  CSSUserIF admin  = authenticate("admin","password");
    	return admin.getPrincipal();
      }

      protected HashMap getContext() {
    	return new HashMap();
      }

      protected CSSUserIF authenticate(String username, String password)
      {
          CSSUserIF user = null;
          System.out.println("Authenticating user: " + username);
          try
          {
              Map context = new HashMap();
              user = cssAPI.authenticate(context, username, password);
              System.out.println("Got User: " + user);
          }
          catch(CSSException ce)
          {
              ce.printStackTrace();
          }

          return user;
      }

      protected void dump(PrintStream out, String msg, String [] arr){
    	  out.println(msg);
    	  for (int i = 0; i < arr.length; i++){
    		  out.println(arr[i]);
    	  }
      }

      protected void dumpUsers(PrintStream out, String msg, CSSUserIF[] users){
    	  out.println(msg);
		  out.println();
    	  for (int i=0 ; i  "+ users[i].getLoginName());
    		  out.println("User Email-->" + users[i].getEmailAddress()[0]);
    		  out.println("User Description-->" + users[i].getDescription());
    		  out.println("User FN -->" + users[i].getFirstName());
    		  out.println("User Identity-->" + users[i].getIdentity());
    		  out.println();
    	  }

      }

      protected void dumpGroups(PrintStream out, String msg, CSSGroupIF[] groups){
    	  out.println(msg);
		  out.println();
    	  for (int i=0 ; i " + groups[i].getName());
    		  out.println("Group Description-->" + groups[i].getDescription());
    		  out.println("Group Identity-->" + groups[i].getIdentity());
    		  out.println();
    	  }

      }

      protected void dumpRoles(PrintStream out, String msg, CSSRoleIF[] roles){
    	  out.println(msg);
		  out.println();
    	  for (int i=0 ; i " + roles[i].getName());
    		  out.println("role Description-->" + roles[i].getDescription());
    		  out.println("role Identity-->" + roles[i].getIdentity());
    		  out.println();
    	  }
      }

      protected abstract void cleanup(String []identities) throws CSSException;

	  protected void printMsg(PrintStream out, String msg) {
		  out.println(msg);
	  }

}

As you see, all this class does is, it authenticates into shared services and provides a set of methods for displaying the groups, users, roles etc. But if you notice, the recommended approach is to use the abstract class method implementation as we need to ensure that when we have multiple instances of the client application the memory is shared across the applications if necessary(this is not always necessary but this is what seems to be the recommended approach by Oracle). So, in order to test this out, we would have to create a sub-class as shown below

package hsssecurity;

import com.hyperion.css.CSSException;

public class hssImplementation extends hsssecurity{
    public hssImplementation() {
    }

    protected void cleanup(String []identities) throws CSSException{
    }

    public static void main(String[] args) {
        hssImplementation a = new hssImplementation();
    }
}

The sub-class would have to provide implementation methods for non-abstract methods in the abstract class. Now, coming to the classpath, you would have to ensure that you have all the jar files under the {HYPERION_HOME}\common\utilities\LCM\9.5.0.0\lib folder to be available to the main executing class.

Once that is done, go to the Run-time execution profile and add an HYPERION_HOME parameter as shown below

With this you should be able to execute any of the methods in the main sample.java file.

The above should get you started on using the Java APIs of shared services. I would cover some more complex integration methods like export/importing users into shared services, custom application to main users/groups etc in the future.