You are on page 1of 23

Its a

Groovy, Groovy, Groovy, Groovy


World
Joe Aultman

Todays Episode:
Get Your gap
Groovy On
Scripting solutions
have a coverage
Groovy bridges the gap
How-To:

Install Groovy
Write a Groovy program
Navigate the Java API
Do things you do with MaxL
Do things you cant do with MaxL

The Automation Landscape


Raw MaxL

essmsh / EAS
No branching / looping, no
interaction
Redirect output to files, parse

Scripting Language + MaxL

Perl / Python*
Full logic, limited Essbase
interaction
Capture Maxl output, parse

API Programs

Compiled Java / VB* / C*


Full logic, full interaction
Direct use of exceptions / error
codes

* not

The Unhappy Valley


Raw MaxL

(no longer)
essmsh / EAS
No branching / looping, no
interaction

Scripting Language + MaxL

Redirect output to files, parse


Perl / Python*
Full logic, limited Essbase
interaction

Scripting Language + API

Capture Maxl output, parse


Groovy
Full logic, full interaction

API Programs

Direct use of exceptions / error


codes
Compiled Java / VB* / C*
Full logic, full interaction

* not

Direct use of exceptions / error

Whats So Groovy About Groovy?


Unparalleled combination of feature richness + Java friendliness
Absolutely, completely, totally, unequivocally, almost 100% syntax compatible with
Java
Class wrappers / main methods not required

println 'Hello World' thats a complete program

Running from uncompiled text is common

Scripts run straight from code -- think it code it run it


No jar or class files

Greatly reduced scaffolding code

Automatic constructors, getters, setters, properties

for (int i=0; i < list.size(); i++){


ItemType item = (ItemType) list.get(i);
// do something with item
}

Whats So Groovy About Groovy?


Dynamic typing

Simple (trivial) variable declarations


They just work (usually)

Adds methods and properties to existing Java classes

Translates getters and setters into properties


mbrList.getAll() mbrList.all

Every object is enhanced


Collections / iterators automatically improved

Powerful enhancements to many specific common Java classes

File
String
Array, List
Map

Closures (OMG, Closures!)

A piece of code wrapped up as an object


Can take arguments and return a value
Can be passed around
Can be used as an anonymous function
Great for iterations

addressBook.each { new Letter(it).send() }

find, findAll, any, every.

Resource handling without tons of trys, catches, and finallys

new File('myfile.txt').eachLine { println it }

Random Acts of Grooviness


Automatic imports of several packages
Optional semicolons

A bigger deal than you might think!

Optional parentheses

This, too!

Optional return statements

The last line of a method is an implicit return

add(x,y) { x + y }

Operator overloading

order.leftShift(item)

becomes order

<< item

Autoboxing allows interesting enhancements to primitive types

If (new Date(f.lastModified()) < 6.months.ago) { f.delete() }


println 'Directions to Carnegie'; 3.times {println 'Practice!'}

In effect, primitives no longer exist (everything is an object)

Man, I Wish I Had Time to Get Into All This


Optional Exception Handling

All exceptions become unchecked exceptions

Safe Dereferencing With ?.


Groovy Truth

Things other than true are true

if(args != null && args.length > 0)

becomes if(args)

Single or Double quotes for strings


Heredocs (triple quoted strings)

def presHead = """Scripting the JAPI:


The Grooviest Things Ever to Happen to Essbase
by Joe Aultman"""

GStrings

println "The date is ${new Date()}."

Ranges

for(i in 1..5){println 'Hi')

or (1..5).each{println

'Hi')

Currying

Fix the value of some parameters instead of hard-coding or passing the same value over and over

Rubber, Meet Road


import
import
import
import

java.io.BufferedReader;
java.io.FileNotFoundException;
java.io.FileReader;
java.io.IOException;

public class WalkFile {


public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("../simpleFile.txt" ));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
}
catch(FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
finally {
if(br != null) {
try {
br.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}
}

new File("../simpleFile.txt").eachLine { line ->


println line
}

Groovy features used:

Automatic imports
No class wrapper
No main method
Automatic resource handling
Iteration with eachLine + closure
Checked exception conversion
(Also optional parentheses, optional
semicolons)

Groovy in Summary
Java compatible (syntax/JVM) dynamic language
Eases many of the pains associated with Java
Adds many (many, many) powerful features to Java
Fun to write (like Perl)
Easy to read (totally NOT like Perl)
What Java-script would be if the name wasn't already taken Thomas Duff,
Amazon Top 100 reviewer
Its awesome

Now about that Essbase JAPI


Set of JARs available for import
Installed with Essbase client (or copy JARs)
Runs in two modes

Client APS Server Essbase Server


Client Essbase Server (Embedded mode)
Requires extra JARs (varies with Essbase version)

Interfaces, interfaces, interfaces

Throughout model and docs


Return objects
Sometimes not all methods/properties available

Main JAPI Objects / Interfaces


IEssbase

.Home.create() gets you started


.signOn

IEssOlapServer

.getApplication

IEssOlapApplication

.getCube

IEssCube

.getOutline
.getMember
.openMemberSelection

Main JAPI Objects / Interfaces


IEssCubeOutline

.associateAttributeMember / .disassociateAttributeMember
.findMember(s) / .findAlias
.moveMember

IEssMember

.createChildMember
.delete
.getChildMembers

IEssMemberSelection

.executeQuery
.getMembers

Common MaxL tasks -- doable with JAPI?

Load data
Load metadata
Run calcs
Assign access
Create/modify filters
Export data
Get server/app/db info
Kill sessions
Create partitions
Unlock objects

Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
No
Yes

Tasks Hard / Impossible with MaxL


Stop and start Essbase itself
Access data values

Balance / compare cubes


Check for data after load

Sort members

By name
By alias
By data value (!)

Audit attributes

Ensure every member has an attribute


Ensure every member has only one attribute

An Example Sorting by Alias


import
import
import
import

com.essbase.api.base.*
com.essbase.api.datasource.*
com.essbase.api.metadata.*
com.essbase.api.session.*

def ess = IEssbase.Home.create(IEssbase.JAPI_VERSION)


def olapSvr = ess.signOn('usr', 'pass', false, null, 'http://aps_svr:13080/aps/JAPI', ess_svr')
def cube = olapSvr.getApplication('app').getCube('db')
def mbrSel = cube.openMemberSelection('')
Dynamic typing saves me from caring about exact object /
mbrSel.executeQuery('<OutputType Binary <SelectMbrInfo (MemberName, MemberAliasName)',
'@CHILDREN("Employee")')
interface names or
the types of objects returned from methods
def empList = new ArrayList()
mbrSel.members.all.each {
empList << [it.getAlias(null) ?: it.name, it.name]
}
empList = empList.sort{it[0]}
empList = empList.reverse()
def otl = cube.openOutline(false, true, true)
def parent = otl.findMember('Employee')
empList.each { mbrArray ->
otl.moveMember(otl.findMember(mbrArray[1]), parent, null)
}
otl.save(IEssCube.EEssRestructureOption.KEEP_ALL_DATA)
cube.unlockOlapFileObject(IEssOlapFileObject.TYPE_OUTLINE, cube.name)
mbrSel.close(); mbrSel = null; otl.close(); otl = null; cube = null;
olapSvr.disconnect(); olapSvr = null; ess.signOff(); ess = null;

This is a cool JAPI method

Looping on IEssIterator enhanced with each and a closure

Elvis operator
Powerful array sorting with closure
Looping with each again

Groovy / JAPI Dos & Donts


DO

refer to the JAPI samples provided with the Essbase client


close it if you open it
unlock it if you lock it
consider static typing in classes & compiled code
reuse code by putting classes in self-named .groovy files

Ex: class EssLoggerOnner in file EssLoggerOnner.groovy


Group files in a directory
Add directory to GROOVY_HOME\conf\groovy-starter.conf
OR add it to the CLASSPATH
Wildcard (directory\*) finds all .jar files
No wildcard (directory\) finds all .class and .groovy files

write self-documenting code, and where you can not, comment generously

Explain design decisions and purpose


Say why it is being done this way, if another way might seem obvious, but is known to have hidden pitfalls

Groovy / JAPI Dos & Donts


DONT

panic
copy and paste from JAPI samples too much

write code that will be hard to read

Groovy makes this harder than some languages


If it must happen, comment like crazy

overuse the think it code it run it paradigm

Miss opportunities to Groovy-cize the code


Stripping static typing and re-doing loops are great ways to make the code just do stuff

Early exits (unfinished code, errors, deliberate bailouts) may cause problems on the Essbase server
Resources may remain locked or processes hung
JAPI code should always clean up after itself

let an evangelist go to waste

Reach out for help


You can find me on LinkedIn

How to Install Groovy


1.

Install a JDK, if not already installed

2.

Set the JAVA_HOME environment variable to point to the JDK

3.

http://groovy.codehaus.org/Download

Unpack the distribution to a directory


Set the GROOVY_HOME environment variable to the Groovy directory

6.
7.

Ex: C:\glassfishv3\jdk

Download a binary distribution of Groovy

4.
5.

http://www.oracle.com/technetwork/java/javaee/downloads/index.html
I use the JDK / EE / Glassfish bundle

Ex: C:\Groovy\Groovy-1.8.0

Add GROOVY_HOME\bin to your PATH environment variable


Test these commands

groovy --version
groovysh
groovyconsole

. Note: The Windows installer does steps 4 - 6

More Information about Groovy


Groovy in Action: the definitive text
Authors include the Groovy project manager and contributors
2nd edition currently in EAP
PDF of 1st edition
Preview PDFs of 2nd edition
First copies of print edition off the presses

Groovy Recipies
Lots of practical advice and real world use cases
The source of many of my examples

Tim Tows Geeky Fix

Essbase error 1042006 on Windows = boost 2 registry settings*


HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
TcpTimedWaitDelay
Data type=REG_DWORD
Default value=0xF0 (240 seconds = 4 minutes)
Valid values=0x1E to 0x12C (30 to 300 seconds)
MaxUserPort
Data type= REG_DWORD
Default value=5000
Valid values= 5,000 to 65,534 (port numbers)

* on the client machine for embedded mode, on the APS server in APS mode

Its a
Groovy, Groovy, Groovy, Groovy
World
Please Fill Out Your Evaluations

Joe Aultman