Wednesday, September 21, 2011

Finding sales offices within a certain distance of a customer

In this post lets do a simple demo that shows all the customers (from the MVDEMO's customers table) on the map. Now, when you click on a customer marker, I want to display all the cities that are within 50 miles radius of the customer. I mentioned sales office in the title to make it sound more interesting, but our small MVDEMO sample data set does not have such a table, so we will use the readily available cities table instead.

Basically, we want to run a query like following when you click on any given customer marker:

select city, state_abrv, location from cities
where sdo_within_distance(location,
sdo_geometry(2001, 8307, sdo_point_type(:1, :2, null), null, null),
:3)='TRUE';



And display the query result as a new theme on the map. Note the three binding parameters in the above query. The first two should be the longitude and latitude of the customer location. The 3rd parameter is a Oracle Spatial WITHIN_DISTANCE operator parameter, typically in the form of 'distance=50 unit=mile'. So a properly bound query looks like this (you can execute it in the mvdemo schema).

select city, state_abrv, location from cities
where sdo_within_distance(location,
sdo_geometry(2001, 8307, sdo_point_type(-122, 37.5, null), null, null),
'distance=50 unit=mile')='TRUE';

We could use a dynamic-query based theme to display the above query result. But, ever mindful of safety and efficiency, we will instead create a pre-defined theme in the mvdemo schema. The trick is to add a query condition that contains these binding variables and disable the default (window-based) spatial filter for the new theme. Below is a screenshot of such a theme (cities_near_customer) and its query condition:



Now that we have the theme defined, we can work on the actual demo itself. The demo page source is found below. Just copy and paste it into an html file, save it in your web server where MapViewer is deployed, and you are all set (assuming the usual mvdemo datasource exists in the MapViewer instance).



<html>
<head>
<META http-equiv="Content-Type" content="text/html" charset=UTF-8">
<TITLE>Map Cache Server/Map Client</TITLE>
<link rel="stylesheet" type="text/css" href="../t.css" />
<script language="Javascript" src="/mapviewer/fsmc/jslib/oraclemaps.js"></script>

<script language=javascript>
var mapview;
var nearestCitiesTheme;

function showMap()
{
var baseURL = "http://"+document.location.host+"/mapviewer";
var mapCenterLon = -122.45;
var mapCenterLat = 37.7706;
var mapZoom = 3;
var mpoint = MVSdoGeometry.createPoint(mapCenterLon,mapCenterLat,8307);
mapview = new MVMapView(document.getElementById("map"), baseURL);
mapview.addMapTileLayer(new MVMapTileLayer("mvdemo.demo_map"));
mapview.setCenter(mpoint);
mapview.setZoomLevel(mapZoom);

var customersTheme = new MVThemeBasedFOI('themebasedfoi1','mvdemo.customers') ;

customersTheme.setBringToTopOnMouseOver(true);

customersTheme.attachEventListener(MVEvent.MOUSE_CLICK, foiClick);
mapview.addThemeBasedFOI(customersTheme);

mapview.display();
}

function foiClick(pointOfClick,foi)
{
alert("Locating all cities within 50 mile radius.");

if(nearestCitiesTheme)
{
mapview.removeThemeBasedFOI(nearestCitiesTheme);
}

nearestCitiesTheme = new MVThemeBasedFOI('cities-theme', 'mvdemo.cities_near_customer');

//set the binding variable for this theme.
var x = foi.x; // :1
var y = foi.y; // :2
var distanceParam = "distance=50 unit=mile"; // :3

nearestCitiesTheme.setQueryParameters(x,y, distanceParam);

nearestCitiesTheme.setBringToTopOnMouseOver(true);
mapview.addThemeBasedFOI(nearestCitiesTheme);
}
</script>
</head>

<body onload="javascript:showMap()">
<h3>Oracle Maps example - finding cities closest to a customer </h3>
<div id="map" style="left:0px; top:10px;width:100%; height:60%"></div>

</body>

</html>





The main things I want to point out here are:

1. It uses a mouse-click listener on the customers theme, so that we can do the magic when user clicks on a customer marker.

2. in the mouse click function (foiClick), we create a new theme-based FOI layer for the cities_near_customers theme. Then we set the 3 binding variables this theme's query condition is expecting, using setQueryParameters().

3. In the demo I want to find out all the cities that are within 50 mile distance of a customer; you can easily use a different distance by changing the value of the distanceParam variable above.

That's all for this post.

-LJ

Monday, July 25, 2011

iOS support in Oracle Maps API

With the latest patch release (version11.1.1.5.1 found here ), MapViewer's Oracle Maps JavaScript API now fully supports iPhone/iPad map interaction using touch events such as pinch to zoom out, double tap to zoom in and other general touch events. Your existing application will automatically get these support once you upgrade to the 11.1.1.5.1 version of MapViewer's oraclemaps.js lib.

In addition to the iOS support, we are also looking into Android support in the future.

Monday, July 18, 2011

Deploying MapViewer on IBM WebSphere 7

I just finished deploying MapViewer (the 11.1.1.5.1 patch release found here ) on IBM WebSphere 7, using the main steps outlined below. Overall I would say it is just a typical process of deploying any J2EE enterprise applications on WebSphere.

1. Log into WebSphere console, and pick the server instance to deploy MapViewer.

2. Start deploying MapViewer by creating a new enterprise application.

3. Download and save the mapviewer.ear file to your local file system if not already done so. Then select this EAR file when prompted. You do not need to unpack this .ear file.

4. Go through the necessary steps by accepting all the defaults as instructed, but note the following special instructions.

At step 7 "Map context roots for web modules", make sure the context root is set to "/mapviewer".

Then at Step 8 "Map security roles to users or groups", make sure the admin user (virtuser in my case) is mapped to the map_admin_role defined by MapViewer. You can ignore the secure_maps_role which is for demo purpose only. Alternatively, you can also map other WebSphere users/groups to this map_admin_role. Later you will use the mapped user or group to log into MapViewer's Admin page.

5. You should get a summery page like below at the end of the deployment steps.



Now save the configuration and finish the deployment process. You should see MapViewer in the applications list, as illustrated below.



6. Next, you need to find where WebSphere stores the mapviewer.ear's unpacked contents. The easiest way to do so, is to start MapViewer and log in to its admin page (by clicking on the Admin button from the home page at /mapviewer). Click the Management tab, then Configuration. Near the top of the page, you will see a line indicating where the mapViewerConfig.xml file was loaded from. In my case, it is:

/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/AppSrv01_Cell01/OracleAS MapViewer.ear/web.war/WEB-INF/conf/mapViewerConfig.xml

This tells us that WebSphere has expanded the mapviewer.ear file into the directory:

/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/AppSrv01_Cell01/OracleAS MapViewer.ear/.

7. Now, we need to modify MapViewer's libraries in order for it to work properly in WebSphere 7.

8. Go to MapViewer's web.war/WEB-INF/lib folder, and physically remove the two jars: jsf-api.jar and jsf-impl.jar. This ensures all MapViewer web pages (which are written in JSF 1.0) work properly in WebSphere, since WebSphere already comes with a set of JSF 1.2 jars, and we don't want our (older) JSF jar files to conflict with these.

9. From your Oracle 11g database install, copy the two JDBC driver related jars, ojdbc5.jar and orai18n.jar, and put them in MapViewer's web.war/WEB-INF/lib folder. Alternatively, you can download these two jars from Oracle's JDBC OTN web page. I used version 11.2.0.2 jars, but earlier versions of these jars should work too.

10. Now, go to WebSphere console and restart the MapViewer application.

From this point on, you will just need to perform typical MapViewer configuration tasks such as adding a new data source et al.

Final note, if before performing step 8 above (where you removed the two jsf jars), you already tried visiting some of the MapViwer pages, then it is likely you will have seen errors related to JSP exceptions. What you need to do (after performing step 8), is go to MapViewer's web.war folder, and touch every .jspx file so that their last modified timestamp gets changed. Do the same for the .jspx files under web.war/admin folder too. This will force WebSphere to re-compile all the .jspx files (using the JSF 1.2 jars that came with WebSphere).