Some days ago, in the MOS OBIEE forum on OTN, I walked into a thread of a user struggling with displaying a Google Map with a marker on an analysis. Of course the marker had to be dynamic based on an address returned by the analysis itself. As the reference used by the user was quite old and the question was about OBIEE 12c I thought it was easier to cover it in a blog post.

First thing to do, split the problem into pieces:
– display a Google map in an analysis
– translate a textual address into a position an the map and display a marker in that location

Display a Google map in an analysis

It must not be difficult to display a map in an analysis as it’s a webpage and there are tons of sites showing google maps, so to find the solution to this one … let’s google it!

https://developers.google.com/maps/documentation/javascript/examples/
All the examples referenced by the Google Maps JavaScript API documentation. The source code is provided and easily tested in JSFiddle.

https://developers.google.com/maps/documentation/javascript/tutorial
A set of tutorials driving you through the various steps and explaining how and why do things.

https://developers.google.com/maps/documentation/javascript/get-api-key
Google maps services are free (for a normal usage) but require a key to allow you to use them.

The very first thing is to get an API key using the link provided in the guide and follow the few steps. As I already had one I didn’t went through this.

As my wish is to have a marker on the map I jumped directly to the Simple Marker example.
The piece of code is really simple and I don’t really care right now if it will show me Australia instead of my own location, all I want is to see a map on my analysis first.

Google explain the code quite well, but let’s highlight the important parts:

  • DIV element with an ID, this ID is used to identify the element where the map will be displayed
  • YOUR_API_KEY in the link to the external (hosted by Google) javascript file, replace it with your own key
  • callback function “initMap” in the link to the external javascript file, can be replaced by what you want, this javascript function will be executed once the library is loaded.

To add this piece of code into an analysis, I used a narrative view as I will want to make the map dynamic by passing values returned by my analysis and the narrative view is the simplest way to do it. Do not forget to tick the “Contains HTML Markup” checkbox!

By default the Content Security Policy jump in and prevent you to load the Google map javascript file.

By default the Content Security Policy jump in and prevent you to load the Google map javascript file.

Nothing appear on the screen, and when you open the javascript console of your browser (Developer tools in Chrome and IE11, Web console in Firefox) the reason is quite explicit.

Content Security Policy (CSP) is a computer security standard introduced to prevent cross-site scripting (XSS), clickjacking and other code injection attacks resulting from execution of malicious content in the trusted web page context. It is a Candidate Recommendation of the W3C working group on Web Application Security, widely supported by the modern web browsers. [wikipedia]

CSP is blocking any script or object coming from a different domain than the one the page belong to if not explicitly allowed by a CSP directive. This is really good as in the past it was possible to load any random javascript file hosted somewhere on any site and do things with it. Most of the time it was to display visualizations but that file was also able to steal the content on your screen and send it out to any random, not friendly, server / organization.

Configure CSP directives in OBIPS

How to set a CSP directive in OBIEE? The documentation must have an answer and it actually does: https://docs.oracle.com/middleware/1221/biee/BIESG/answersconfigset.htm#BIESG9326
The syntax is simple and sites like https://content-security-policy.com/ provides some extra details on the possible values to use.

After some testing (allow one element, retry, add the new blocked references etc.) this is what I come up with:

Adding this config into the instanceconfig.xml file (inside the <ServerInstance><Security> tags), restart OBIPS (only this one from Enterprise Manager, it takes 10 seconds) and the sample map with marker is supposed to appear.

Google map with markers

The Google map Simple marker example perfectly works.

The Google map Simple marker example perfectly works.

To give it a try with my own data I took a file containing locations (coordinates) of cars counters installed in Switzerland and the daily average number of cars over a month. (The data is freely available from https://opendata.swiss/en/)

Google map integration in analysis - Cars counters in Switzerland
The coordinates uses the WGS84 longitude and latitude format, for example 6.31994652 E, 46.44438742 N. The “title” attribute of a marker is just a text for when you mouse-over one of the markers. The code to achieve that is the previous one slightly adapted to call multiple times the “new google.maps.Marker” function to add all my markers.

Using a Narrative view it's possible to easily pass values to javascript.

Using a Narrative view it’s possible to easily pass values to javascript.

 

Geocode an address: get the coordinates from a text

Last step is now to implement geocoding to translate a textual address in the form of street, post code, location into a format the map can understand to place a marker (WGS84 decimal coordinates). For this example I took the list of post offices in the area of Lausanne (Switzerland) with the name of the post office and the address.

Text addresses are translated into coordinates by Google Geocoder API.

Text addresses are translated into coordinates by Google Geocoder API.

The  geocoding code sample on Google Maps examples gives all the logic. All I needed to do was cut the code in pieces to use it in a narrative view, to call the “geocodeAddress” function as many times as needed.

The call to the "geocodeAddress" function receive as parameters the address and name of the post office as label for the marker.

The call to the “geocodeAddress” function receive as parameters the address and name of the post office as label for the marker.

Done !
I have now a Google map embedded into my analysis and I can display on it markers with coordinates or from textual addresses. The Google samples provide many more example of things it’s possible to do on these maps.

Geocode upfront

Please keep in mind the geocoding calls are limited, so if you geocode 50 address on a map you will get errors because of too many queries. Consider doing the geocoding once upfront and store the coordinates in your database as it will be faster to display and you will not be blocked by the API query limits.

Share This