Download - FDMEE JythonScripting
Jython Scripting in FDMEEIt's Not That Scary
Tony Scalese
Edgewater Ranzal
Focus
Services
People
Methodology
Customers
Partnership
15 Years700+ clients
1000+ projects
About Edgewater Ranzal
We offer a full spectrum of EPM/BI ServicesDashboards & Scorecards, Financial
Analytics & Reporting, Operational Analytics,
What-if Analysis, Query & Reporting, Visual
Exploration
Financial performance, Legal,
Segment & Mgmt Reporting, Financial
Close
HFM Optimization, Performance Lab
SOX Compliance Support
Strategic Finance, Planning,
Budgeting, Forecasting, Workforce
Planning, Capital Planning, Project
Financial Planning
Data Integration, Financial Data
Management, Data Warehousing,
Master Data Management &DRM,
ETL Services, Automation
Project/Program Mgmt, EPM
Road Maps, Application
Reviews, Business
Requirements, Process
Change, Documentation
Installation, Upgrades,
Migration, System
Monitoring, Backup and
Recovery, Disaster
Recovery, Load Testing,
Hardware Sizing, Exalytics
Benchmarking
Consolidation
BusinessIntelligence
EnterprisePlanning
Infrastructure
Training &Support Services
ProjectManagement
DataServices
Costing & Profitability
Mgmt
Support Services – Infrastructure &
Application Support Contracts
Key Teach Course Delivery: Planning, Essbase,
Financial Reporting, Smart View, HPCM, HFM,
FDM, DRM, OBIEE
Custom Training Delivery: Process & Reporting
HPCM Standard & Detailed
Models, Waterfall Allocations,
Activity Based Costing,
Customer, Product & LOB
Profitability
� Jython Overview
� Configuring Eclipse
� FDMEE Scripting Configuration
Agenda
� Why Jython and not
VBScript?
● Jython is the strategic direction
of Oracle development
● Jython is platform independent
● The API supporting Jython
scripting will continue to be
enhanced
● Jython error handling is more
elegant and robust
Let’s Get It Out of the Way
� Python programming language written in JAVA
� Syntax is more sensitive than VBScript
� Variable data type is critical; declaration is implicit
� Comment characters: # or ‘’’<comment block>’’’
� import statement allows easy reuse of code
� Far more robust error handling
� Familiarize yourself with camelCase
� Not that different than VBScript
Jython Basics
� Import JAVA classes
import java.sql as sql
� Utilize Try...Except
try:
Code to execute
except:
Error handling
Script Format
� Sys, Traceback: Can be used to get detailed
error information including line in script
producing error
� Java.sql: Used to interact with remote
databases
� Smtplib: Used for email generation
Commonly Used JAVA Classes
Method Functionality
count(Substring,[Start],[End]) Number of times substring occurs
endswith(Suffix,[Start],[End]) Boolean result; does string end with suffix
find(substring,[Start],[End]) Returns position where substring is found
isdigit() Boolean result; is string all numbers
isspace() Boolean result; is string all spaces
lower() Puts still in all lower case, similar to lcase
replace(old,new,[count]) Replaces text in string
split([separator],[max split]) Returns a list, string is divided by separator
startswith(prefix,[Start],[End]) Boolean result; does string start with prefix
strip([characters]) Removes specified character(s) from string
upper() Puts still in all upper case, similar to ucase
zfill(width) Returns numeric string filled left with zeros
Jython String Manipulation
Jython VBScript
If Then if x == 100:
elif x == 200:
else:
If x = 100 then
Elseif x = 200 then
Else
End if
Case No native statement;
utilize dictionary or If
Then statements
Select Case x
Case 100
Case 200
Case Else
End Select
Jython Statements
Jython VBScript
Do Loop while x<100:
Do something
x += 1
Do while x < 100
Do something
x = x+1
Loop
For Loop for x in range(100):
Do something
For x = 0 to 100
Do something
Next
Jython Iteration
Jython VBScript
List lListName = [‘Elem1’,’Elem2’,’Elem3’]
for elem in lListName:
print elem
aArrayName =
Array(“Elem1”,”Elem2”,”Elem3”)
For each strElem in aArrayName
msgbox strElem
Next
Dictionary dictName = {}
dictName[‘Tony Scalese’] = 36
dictName[‘Opal Alapat’] = 39
for sKey,sItem in dictName.iteritems():
print sKey + ‘\’s age is ‘ + str(sItem)
Set dictName =
CreateObject(“Scripting.Dictionary”)
dictName.Add “Tony Scalese”, 36
dictName.Add “Opal Alapat”, 39
For each strKey in dictName.Keys
msgbox strKey & “’s age is “ &
dictName.Item(strKey)
Next
Jython Mapping Data Type
� If a JRE is not installed, be sure to install the 64
bit JRE (install using defaults)
● http://www.oracle.com/technetwork/java/javase/dow
nloads/jre7-downloads-1880261.html
JAVA Runtime Environment (JRE)
� Download Jython 2.5.1 from
http://www.jython.org/downloads.html
● Do not use a more up to date version!
Jython Download
� Select English � Next
� Accept the EULA � Next
� Select Standard � Next
� Leave the default C:\Jython2.5.1 directory � Next
� May be prompted that the directory is created, click OK and Next again
� Leave Current as JAVA home directory � Next
� Click Next on the Summary tab, install will begin
� Click Next on the ReadMe and then Finish
Jython Install
� Confirm the C:\jython2.5.1 directory exists
� Confirm jython.jar file exists
Jython Install Confirmation
� Download Eclipse Standard from
http://www.eclipse.org/downloads/
Download Eclipse
� Extract the download to the C:\ directory
� Open the C:\Eclipse folder and launch
eclipse.exe
Extract Eclipse
� Specify a default workspace
Workspace
� Expand General �Editors and click Text Editors
� Change the options:● Display tab width: 2
● Insert spaces for tabs: Checked
● Show Print Margin: Checked
● Show Line Numbers: Checked
Configure Eclipse General Options
� Select Windows � Preferences
� Expand Install/Update
� Click Available Software Sites
� Click Add
� Name: PyDev
� Location: http://pydev.org/updates/
� Click OK
Install PyDev
PyDev Install
� Select Help � Install New Software� Click PyDev from the Work With drop down� Check PyDev� Click Next� Click Next� Accept the EULA and click Finish
PyDev Install
� Put a check next to the
certificate
� Click OK
� Click Yes to restart Eclipse
after the install
PyDev Install
� Windows � Preferences
� Expand PyDev and click Editor
� Change tab length to 2
Set PyDev Options
� Interpreter – Jython
� Click New
● Interpreter Name: Jython2.5.1
● Browse and select Jython.jar from C: drive
� Click OK
Set PyDev Interpreter
� When prompted, leave defaults and click OK
Set PyDev Interpreter
� Close the Welcome Screen
� Right click the Package Explorer
� New � Project
Creating a Project
� Expand PyDev and select PyDev Project
� Click Next
Creating a Project
� Name the Project
� Change the project type to Jython
� Click Finish
� Click Yes when prompted
Creating a Project
� Right click the Project
� Select New � Folder
● Name the folder src
● Repeat and create as lib
Organize Code
� Right click lib folder and select Import
� Expand General and select File System
Import JAR Files
� From Directory: lib directory of FDM
● %hyperion_home%\Products\FinancialDataQuality\li
b
� Check the aif-apis.jar
� Click Finish
Import FDMEE JAR
� Right click the project (ER_FDMEE)
� Select Properties
� Click PyDev – PYTHONPATH
� Click Add jar/zip/egg
� Expand the project and click the lib folder
Update Python Path
� Add new PyDev module
● Right click src folder
● New � PyDev module
Creating Modules
� Specify a name
� Click Finish
� When prompted for a template, select Module
main and click OK
Creating Modules
� Add print “hello”
� Run the script
● Run as Jython Run
� hello shows in the
console window when
successful
Testing Module
� Add the following text to the module:● import com.hyperion.aif.scripting.API as API
� Save the module
� Type API(). on a new line.
� A list of available methods will display
Testing FDMEE API Usage
� The equivalent of Import – Data Pump scripts in FDM Classic
� Import Integration scripts have been replaced by the Open Interface adaptor and the BefImport event script
� Import scripts are used to manipulate data during the import process
� Execute during an import process when assigned to the import format used by the location and data load rule
� Every line in the data file is evaluated
� Avoid the temptation to overuse import scripts● Parsing strings that cannot be parsed by an import format● Temporary variables storing header information● Mapping data should be done in maps, not import scripts
Import Scripts
� Define the script name
● def ScriptName (strfield,strrecord):
� Write script actions
● aField = split(strrecord,”-”)
● sCostCenter = aField[1]
� Return result to function
● return sCostCenter
Import Script SyntaxNotice the
colon at the
end
def EBS_CostCenter(strField, strRecord):
sCC = strField
if strField.count(“.”) > 0:
aSegments = strField.split(‘.’)
sCC = aSegments[2]
return sCC
Sample Import Script
Notice the
colon at the
end
� No longer limited to 5
� Declare a variable before the function
� Designate the variable as global
strDept = “”
def Nvision_Entity(strfield,strrecord):
if strrecord[1:5] == “Dept:”:
global strDept
strDept = strrecord[6:9]
return strfield
Temporary Variables (RES.pVarTempx)
� Simply return temporary variable in “assign”
script
def Nvision_C1(strfield,strrecord):
return strDept
Using Temporary Variables
� Similar in concept to varValues
� Be careful of overuse due to performance
impacts
� Enter #SCRIPT to activate script section of
maps
� fdmRow.getString(“FieldName”)
� fdmResult = “Mapped_Result”
Mapping Scripts
� Execute during defined events within the
application
� Fewer than FDM Classic, notably StartUp,
POVChanged
� Scope needs to be well defined to ensure
process only executes when needed
� No need to declare function
● def BefImport(): Not needed
Event Scripts
Event Description FDM Classic Equivalent
Import Executes any time the import
process is executed
ImportAction, FileImport
Calculate Before & After Logic groups and
maps processing
Calculate
ProcLogicGrp When logic groups are assigned ProcLogicGroup
ProcMap Executes ONCE during mapping
application
ProcMap
Validate Validate workflow step Validate
ExportToDat Export workflow step ExportToDat
Load Export workflow step Load
Consolidate Export workflow step Consolidate
Check Check workflow step Check
Events – Before and After
� Custom scripts are used to extend the functionality of FDMEE
� Custom script are organized in groups
● Scripts can be assigned to multiple groups
� Custom scripts are registered
● Similar to Menu Maker specifying a caption
● Parameters can be added to make a script more dynamic
� Custom scripts can executed from web UI
� No need to declare function
● def ER_OutputData(): Not needed
Custom Scripts
� Create a group
● Logical grouping that a user can select
● By Region: North America, EMEA, Asia Pacific
● By Purpose: Data Exports, Budget, Actuals
� Register script to group
● Add parameters if applicable
Custom Script Registration
� Select Group
� Select Script & click Execute
● Specify parameters if applicable
� Select Execution Mode and click OK
Executing Custom Scripts
� Used to test code without actually impacting the
data in FDMEE
� 4 sections:
1. Initialize dev mode
2. Populate context
3. Custom code
4. Clean-up actions
� Once code is tested, sections 1, 2 & 4 can be
removed, handled natively by the application
Development Mode
Commonly Used Occasionally Used Rarely Used
APPID
CATKEY
CATNAME
CHKSTATUS
EXPSTATUS
IMPSTATUS
INBOXDIR
LOADID
LOCKEY
LOCNAME
OUTBOXDIR
PERIODNAME
PERIODKEY
PROCESSSTATUS
SCRIPTSDIR
VALSTATUS
EXPORTFLAG
EXPORTMODE
FILEDIR
FILENAME
IMPORTFLAG
IMPORTFORMAT
IMPORTMODE
MULTIPERIODLOAD
RULEID
RULENAME
SOURCENAME
SOURCETYPE
TARGETAPPDB
TARGETAPPNAME
BATCHSCRIPTDIR
EPMORACLEHOME
EPMORACLEINSTANCEHOME
FDM Context
� Each execution includes a collection of information
import java.math.BigDecimal as BigDecimalimport java.sql as sqlimport com.hyperion.aif.scripting.API as API
fdmAPI = API()
conn = sql.DriverManager.getConnection("jdbc:oracle:thin:@server:port:SID", "user", "password");conn.setAutoCommit(False)
fdmAPI.initializeDevMode(conn);
print “Connected”
Initialize Development Mode
fdmContext = fdmAPI.initContext(BigDecimal(LoadID))
print “Location Name: “ + fdmContext[“LOCNAME”]
Populate Context
� fdmAPI.closeConnection();
Clean-up Action
� getPOVLocation(LoadID), Category, StartPeriod, EndPeriod: Returns key, not text
� executeDML(query,param_list)
� getCustomScriptParameterValue(loadID,param): Load ID is optional
� executeQuery(query,parameters): Returns recordset
� showCustomFile(FilePath): Display file
� showCustomMessage(message)
� logFatal(message), Error, Warn, Info, Debug
Useful FDM APIs
� The BefImport event script is used in
conjunction with the Open Interface adaptor to
import data from relational source
� This approach replaces import integration
scripts from FDM Classic
� Check out Mike Casey’s presentation - Using
the Open Interface Adapter in FDM Enterprise
Edition 11.1.2.3 - on 6/25 from 2-3 for a deep
dive into the setup
Integrating Data from Relational Sources
import java.text.SimpleDateFormat as SimpleDateFormat
import java.sql as sql
strPOVPer = fdmContext["PERIODKEY"]
strYear = SimpleDateFormat("yyyy").format(strPOVPer)
lngMonth = SimpleDateFormat("MM").format(strPOVPer)
strMonth = SimpleDateFormat("MMM").format(strPOVPer)
batchName = "MatchDataLoadRuleParam"
BefImport Script Sample - Setup
insertStmt = """
INSERT INTO AIF_OPEN_INTERFACE (
BATCH_NAME
,YEAR
,PERIOD
,PERIOD_NUM
,CURRENCY
,COL01
,COL02
,AMOUNT
) VALUES (
?
,?
,?
,?
,?
,?
,?
)
"""
BefImport Script Sample – Build Query
#Connect to source DB
sourceConn = sql.DriverManager.getConnection("jdbc:oracle:thin:@Server:Port:SID","User","Password");
#Build SELECT statement to get data to insert
selectStmt = "Select * from table \n"
selectStmt = selectStmt + "Where 1=1 \n"
#Run the query to get the data
stmt = sourceConn.prepareStatement(selectStmt)
RS = stmt.executeQuery()
BefImport Script Sample – Run Query
#Loop through the data and import it into the Open Interface table
while(RS.next()):
params = [ batchName, strYear,strMonth,lngMonth, "USD", RS.getString("Account"), RS.getString("Entity"), RS.getBigDecimal("Amount") ]
fdmAPI.executeDML(insertStmt, params, False)
fdmAPI.commitTransaction()
#Close the connection
RS.close()
sourceConn.close()
BefImport Script Sample – Import Data
Questions