top of page
  • Writer's pictureSarah Ansell

Tips for using REST API and groovy to run jobs in Oracle Cloud EPM Planning

Updated: Apr 26


1. Set up your connection URL for flexibility to use with different REST API job types.

When configuring the Other Web Service Provider type connection, I prefer to use the URL:

http://localhost:9000

This has the following benefits:

  • When migrating between Production and Test environments, the URL does not need to be amended. The password will still need to be re-entered as with all Connections.

  • The URL required by different REST API commands can be supplied within the groovy script itself. This allows you to have one business rule that uses REST to launch a Data Integrations, whilst another will launch a Business Rule. Both of these require different URLs. When using the localhost URL you can use a single Connection. That's less password maintenance!


To use this method, you will need to post the remainder of the URL path in the REST request. "http://localhost:9000" will become the equivalent of your environment URL ending in "...oraclecloud.com". The path that needs to be suffixed is dependent on which REST API request you are using and you will need to check this in the Oracle documentation.


When referencing your connection within your script use the following for launching business rules:

HttpResponse<String> jsonResponse = operation.application.getConnection("Local REST Connection").post('/HyperionPlanning/rest/v3/applications/InsertAppName/jobs')
.header("Content-Type", "application/json")
.body(json(["jobType":"Rules", "jobName":"Rule1", "parameters":["RTPName":rtps.RTPName.toString()]]))
.asString();

Alternatively, you could use the following connection path for posting a data integration request.

.post('/aif/rest/V1/jobs') 

2. Reference Run Time Prompts as follows

In the top of your script include this comment. Add the run time prompts to register them for the script:

/* RTPS: {RTP1Name}, {RTP2Name} */

When referencing the run time prompt for actual use in your groovy code reference as follows:

println rtps.RTP1Name

Or, you might need it in string format to use within a command, as follows:

rtps.RTPName.toString()

If you want elaboration on this, there are plenty of blogs out there about the way Groovy handles these.


3. Be careful with brackets and capital letters when copying the REST API commands in the Oracle documentation.

Use the documentation rather than examples online if you can because there is less room for error and all the parameters you might need are referenced - for example see below for the launch Rules command:

Just make sure that you remember to convert the curly brackets {} in the example payload to square brackets [] as required by groovy.

Groovy is case sensitive so always check your capitalisation - for example jobType must be exactly the same - not jobtype, JobType, JOBTYPE - it's very easy to overlook. You might receive BAD_REQUEST as the status message.


3. If using groovy / rest to launch a business rule - make sure the rule is deployed

The need to use groovy / REST to launch a business rule is rare, but if you do, make sure the rule is deployed from calculation manager, otherwise you will get a 'BAD_REQUEST' status (which can mean many things!)

In the full jsonResponse.body you will see a more useful error along the lines of 'cannot find business rule'.


4. If it isn't working, don't just rely on the $jsonResponse.statusText" error

Some of the errors can be useful, but you always need more when first creating a rule or troubleshooting.

Use the following in your script after the main REST command:

println jsonResponse.body

This will give a lot more information - but not in the most elegant way. When happy with the rule, return to jsonResponse.statusText for a simplified error.


5. Keep it simple first

The 'awaitCompletion' part of REST API commands can be fiddly to break down and understand. Before worrying about needing to change that, just try keeping it simple and posting the REST API command only. This part:

HttpResponse<String> jsonResponse = operation.application.getConnection("Local REST Connection").post('/HyperionPlanning/rest/v3/applications/InsertAppName/jobs')
.header("Content-Type", "application/json")
.body(json(["jobType":"Rules", "jobName":"Rule1", "parameters":["RTPName":rtps.RTPName.toString()]]))
.asString()

Launch the rule, and see if it kicks of the desired action in the job console. Note that there is no error handling with this text alone - so you will only know if it is working by seeing the jobs in the job console.


If this doesn't work, you know this part is wrong, the awaitCompletion part could be working fine.

Add the "println jsonResponse.body" in to help you diagnose what is wrong.

Once happy with this section, add in your full error handling / waiting for the job to complete:

// Await Completion //
Boolean JobSuccess = awaitCompletion(jsonResponse, "Local REST Connection", "Job")
// Throw error if the job errors //
if (JobSuccess == false){throwVetoException("Error running rule please view log details ($jsonResponse.statusText)")}

def awaitCompletion(HttpResponse<String> jsonResponse, String connectionName, String operation) {
    final int IN_PROGRESS = -1
    if (!(200..299).contains(jsonResponse.status))
    throwVetoException("Error occured: $jsonResponse.statusText")

    // Process Status and Print to Log //
    ReadContext ctx = JsonPath.parse(jsonResponse.body)
    int jobId = Integer.valueOf((String)ctx.read('$.jobId'))
    int status = ctx.read('$.status')
    for(long delay = 50; status == IN_PROGRESS; delay = Math.min(1000, delay * 2)) {
        sleep(delay)
        status = getJobStatus(connectionName, (String)ctx.read('$.jobId'))
    }
    println("$operation ${status == 0 ? "completed successfully" : "failed, please see log for further details"}.\n")
    return status == 0
}

// Read Job Status //
int getJobStatus(String connectionName, String jobId) {
    HttpResponse<String> pingResponse = operation.application.getConnection(connectionName).get("/HyperionPlanning/rest/v3/applications/InsertAppName/jobs/" + jobId).asString()
    return JsonPath.parse(pingResponse.body).read('$.status')
    }

0 comments
bottom of page