In OBIEE 12c data-model-cmd
is a wrapper for some java code which ultimately calls an internal RESTful web service in OBIEE 12c, bi-lcm
. We saw in the previous post how these internal web services can be opened up slightly, and we’re going to do the same again here. Which means, time for the same caveat:
None of these Web Services are documented, and they should therefore be assumed to be completely unsupported by Oracle. This article is purely for geek interest. Using undocumented APIs leaves you at risk of the API changing at any time.
With that out of the way, let’s go! Firstly, a simple example of downloading the RPD. The way that OBIEE 12c works with RPDs is significantly different from previous versions, since there is now the concept of customisations and layering. You may have noticed liverpd.rpd
or default_diff.xml
, both of which are related to this. The nett result is that there is no longer a single RPD file uploaded to the server which can be downloaded again for editing, as there was in 11g and before. You now need to submit a request to OBIEE to retrieve the latest version of the RPD, which it will pull together on the fly and pass back to you. This is done using data-model-cmd
:
$ /app/oracle/biee/user_projects/domains/bi/bitools/bin/data-model-cmd.sh downloadrpd -O ~/myRPD.rpd -W Admin123 -U weblogic -P Admin123 -SI ssi
This writes a local file, myRPD.rpd. In the background, it’s calling bi-lcm
to retrieve the file, as we can see from two diagnostic routes:
-
First, my favourite,
sysdig
, sniffing any traffic on ports 7780 (managed server public listen port) and 7783 (managed server internal listen port, as used by intra-component REST calls etc):sudo sysdig -s 2000 -A -c echo_fds "(fd.port=7780 or fd.port=7783)"
This captures the following
POST
request:POST /bi-lcm/v1/si/ssi/rpd/downloadrpd HTTP/1.1 Content-Type: application/x-www-form-urlencoded Authorization: Basic d2VibG9naWM6QWRtaW4xMjM= User-Agent: Jersey/2.21.1 (HttpUrlConnection 1.8.0_51) Host: demo.us.oracle.com:7780 Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive Content-Length: 24
-
Just as useful, in this case, is the
bi-lcm
log file itself,DOMAIN_HOME/servers/bi_server1/logs/bi-lcm-rest.log.0
:47 > POST http://demo.us.oracle.com:7780/bi-lcm/v1/si/ssi/rpd/downloadrpd 47 > Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 47 > Authorization: Basic d2VibG9naWM6QWRtaW4xMjM= 47 > Connection: keep-alive 47 > Content-Length: 24 47 > Content-Type: application/x-www-form-urlencoded 47 > Host: demo.us.oracle.com:7780 47 > User-Agent: Jersey/2.21.1 (HttpUrlConnection 1.8.0_51) target-password=Admin123
So the syntax of the RESTful call is pretty simple – call the downloadrpd
endpoint, passing in the password that is to be used to encrypt the generated RPD. Authentication is done by Basic HTTP.
What can we do with this? Two things - neither of which are spectacularly useful as such, but additional ways and means to achieve the same. It may be you’ve got a bespoke code integration system that needs to integrate with a RESTful endpoint, or simply it’s just another useful tool to have at one’s disposal. Before we get into it, it’s probably time for that caveat again:
None of these Web Services are documented, and they should therefore be assumed to be completely unsupported by Oracle. This article is purely for geek interest. Using undocumented APIs leaves you at risk of the API changing at any time.
cURL
is a commandline utility for sending HTTP (amongst other) requests. We can use it to request the RPD to be downloaded to any machine on which we can run cURL. Because it adheres to the *nix philosophy of making the output available as a pipe, we can redirect it to a file: (if you don’t, you’ll get a screen full of gibberish…)
curl -X "POST" "http://192.168.56.101:7780/bi-lcm/v1/si/ssi/rpd/downloadrpd" \
--data-urlencode "target-password=Admin123" \
--basic --user weblogic:Admin123 \
> downloadedRPD.rpd
Note that I’ve used \
line continuation character to break the command over multiple lines simply for legibility.
It’s pretty clear, hopefully, how to parameterise this for your own use. The server and port are your OBIEE managed server and port (the same that /analytics
is on). The rest are credentials, for the downloaded RPD, and to access the OBIEE system, respectively.
Taking the same method, but via a web page, we can run this HTML file anywhere we want:
<html>
<head></head>
<body>
<FORM action="http://192.168.56.101:7780/bi-lcm/v1/si/ssi/rpd/downloadrpd"
enctype="application/x-www-form-urlencoded"
method="post">
<P>
New password for downloaded RPD file? <INPUT type="text" name="target-password"><BR>
<INPUT type="submit" value="Send"> <INPUT type="reset">
</FORM>
</body>
</html>
Load it into a web browser, enter a password for the generated RPD:
and enter your credentials for OBIEE when prompted:
The RPD file is downloaded as downloadrpd
, which you can rename to whatever you want.
So, we can do downloadrpd
– what about uploadrpd
? Because that really would be useful for some people, being able to deploy an RPD without needing to dive into the commandline.
Here’s the uploadrpd
command:
$ /app/oracle/biee/user_projects/domains/bi/bitools/bin/data-model-cmd.sh \
uploadrpd -I /home/oracle/chng1.rpd -W Admin123 -U weblogic -P Admin123 -SI ssi
The resulting POST request looks like this:
POST http://demo.us.oracle.com:7780/bi-lcm/v1/si/ssi/rpd/uploadrpd
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Authorization: Basic d2VibG9naWM6QWRtaW4xMjM=
Connection: keep-alive
Content-Length: 1221056
Content-Type: multipart/form-data;boundary=Boundary_1_1010953501_1464461679148
Host: demo.us.oracle.com:7780
MIME-Version: 1.0
User-Agent: Jersey/2.21.1 (HttpUrlConnection 1.8.0_51)
The upload has two parts; the RPD password, and the RPD itself.
--Boundary_1_1010953501_1464461679148
Content-Type: text/plain
Content-Disposition: form-data; name="rpd-password"
Admin123
--Boundary_1_1010953501_1464461679148
Content-Type: application/vnd.oracle.rpd
Content-Disposition: form-data; filename="myRPD.rpd"; modification-date="Sat, 28 May 2016 18:53:14 GMT"; size=1220668; name="file"
[whole bunch of encoded RPD binary file]
But - I couldn’t replicate this HTTP request successfully; called manually through Paw, or cURL, or a manual webpage like the above, it would fail with the error:
oracle.bi.lcm.rest.si.rpd.RpdEndpointV1 SEVERE - Exception during RPD file upload: java.lang.NullPointerException
Or on other attempts:
java.net.SocketTimeoutException : Read time out after 30000 millis
My guess (based on ruling out all the other stuff) is it’s down to how I was encoding the file and/or specifying its length. A challenge for you Neos out there to crack?
Update: Neo has risen to the challenge, showing that the force is strong in this one… Andrew Fomin (twitter | blog) has figured out the correct syntax in order to use curl
to upload an RPD:
curl -X POST \
"http://192.168.1.41:7780/bi-lcm/v1/si/ssi/rpd/uploadrpd" \
--form "[email protected];type=application/vnd.oracle.rpd" \
--form "rpd-password=Password01" \
--basic --user weblogic:Admin123
The key bit in this is that the content-type of the upload RPD file is set to application/vnd.oracle.rpd
– without this the upload fails.
When run, the JSON payload returned shows success (parsed here through jq
):
{
"clazz": [
"rpd-response"
],
"links": [
{
"href": "http://192.168.1.41:7780/bi-lcm/v1/si/ssi/rpd/uploadrpd",
"rel": [
"self"
]
}
],
"properties": {
"entry": [
{
"key": "si",
"value": {
"type": "string",
"value": "ssi"
}
},
{
"key": "description",
"value": {
"type": "string",
"value": "RPD upload completed successfully."
}
},
{
"key": "desc_code",
"value": {
"type": "string",
"value": "DESC_CODE_RPD_UPLOAD_SUCCESSFUL"
}
},
{
"key": "status",
"value": {
"type": "string",
"value": "SUCCESS"
}
}
]
},
"title": "RPD-LCM response, SI=ssi, action=Upload RPD"
}
Thanks Andrew!
None of these Web Services are documented, and they should therefore be assumed to be completely unsupported by Oracle. This article is purely for geek interest. Using undocumented APIs leaves you at risk of the API changing at any time.