tag:blogger.com,1999:blog-67749036657521069512024-03-13T17:01:47.525-04:00Oracle MapViewerAll things Oracle MapViewer.Unknownnoreply@blogger.comBlogger49125tag:blogger.com,1999:blog-6774903665752106951.post-29714713169338719012013-04-09T20:45:00.002-04:002013-04-09T20:45:48.934-04:00We have a new home!Hi folks,<br />
Sorry for not updating this blog for a while; been super busy getting the latest mapViewer released. Now that MapViewer version 11.1.1.7.0 (PS6) is officially out, be sure to check out the latest and greatest version here:<br />
<br />
<a href="http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html">http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html </a><br />
<br />
Some key new features include our brand new, written from scratch HTML5 JavaScript mapping API, a brand new spatial data editor, a new sample data set, a standalone samples app, a Glassfish-based Quick Start kit, as well as many other cool new features.<br />
<br />
We are also glad to announce that we now have an official Oracle MapViewer blog hosted by none other than Oracle's own blog server. Please be sure to check us out at the new address: <br />
<br />
<a href="https://blogs.oracle.com/oracle_maps_blog"><b>https://blogs.oracle.com/oracle_maps_blog</b></a><br />
<br />
Key team members and managers are in the process of getting their account approved and will be joining the new blog soon. You will sure see a much more active blog for sure.<br />
<br />
Thanks and till our next post at the new site,<br />
<br />
LJ
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-58363407183396749572011-09-21T22:04:00.004-04:002011-09-21T22:42:51.477-04:00Finding sales offices within a certain distance of a customerIn 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.<br /><br />Basically, we want to run a query like following when you click on any given customer marker:<br /><br /><span style="font-weight:bold;">select city, state_abrv, location from cities<br />where sdo_within_distance(location,<br /> sdo_geometry(2001, 8307, sdo_point_type(:1, :2, null), null, null),<br />:3)='TRUE';</span><br /><br /><br />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).<br /><br />select city, state_abrv, location from cities<br /> where sdo_within_distance(location, <br /> sdo_geometry(2001, 8307, sdo_point_type(-122, 37.5, null), null, null), <br />'distance=50 unit=mile')='TRUE';<br /><br />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:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-i5mAWtVFruc/TnqafrKBrWI/AAAAAAAAAIQ/zNDuGC4NT80/s1600/nearest.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 224px;" src="http://4.bp.blogspot.com/-i5mAWtVFruc/TnqafrKBrWI/AAAAAAAAAIQ/zNDuGC4NT80/s320/nearest.png" alt="" id="BLOGGER_PHOTO_ID_5655002151068478818" border="0" /></a><br /><br />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).<br /><br /><pre><br /><br /><html><br /><head><br /><META http-equiv="Content-Type" content="text/html" charset=UTF-8"><br /><TITLE>Map Cache Server/Map Client</TITLE><br /><link rel="stylesheet" type="text/css" href="../t.css" /><br /><script language="Javascript" src="/mapviewer/fsmc/jslib/oraclemaps.js"></script><br /><br /><script language=javascript><br /> var mapview;<br /> var nearestCitiesTheme;<br /> <br /> function showMap() <br /> { <br /> var baseURL = "http://"+document.location.host+"/mapviewer";<br /> var mapCenterLon = -122.45;<br /> var mapCenterLat = 37.7706;<br /> var mapZoom = 3; <br /> var mpoint = MVSdoGeometry.createPoint(mapCenterLon,mapCenterLat,8307);<br /> mapview = new MVMapView(document.getElementById("map"), baseURL);<br /> mapview.addMapTileLayer(new MVMapTileLayer("mvdemo.demo_map")); <br /> mapview.setCenter(mpoint); <br /> mapview.setZoomLevel(mapZoom); <br /> <br /> var customersTheme = new MVThemeBasedFOI('themebasedfoi1','mvdemo.customers') ;<br /> <br /> customersTheme.setBringToTopOnMouseOver(true);<br /> <br /> customersTheme.attachEventListener(MVEvent.MOUSE_CLICK, foiClick);<br /> mapview.addThemeBasedFOI(customersTheme);<br /> <br /> mapview.display();<br /> } <br /><br /> function foiClick(pointOfClick,foi)<br /> {<br /> alert("Locating all cities within 50 mile radius.");<br /> <br /> if(nearestCitiesTheme)<br /> {<br /> mapview.removeThemeBasedFOI(nearestCitiesTheme);<br /> }<br /> <br /> nearestCitiesTheme = new MVThemeBasedFOI('cities-theme', 'mvdemo.cities_near_customer');<br /> <br /> //set the binding variable for this theme.<br /> var x = foi.x; // :1<br /> var y = foi.y; // :2<br /> var distanceParam = "distance=50 unit=mile"; // :3<br /> <br /> nearestCitiesTheme.setQueryParameters(x,y, distanceParam); <br /> <br /> nearestCitiesTheme.setBringToTopOnMouseOver(true);<br /> mapview.addThemeBasedFOI(nearestCitiesTheme);<br /> }<br /></script><br /></head><br /><br /><body onload="javascript:showMap()"><br /><h3>Oracle Maps example - finding cities closest to a customer </h3><br /> <div id="map" style="left:0px; top:10px;width:100%; height:60%"></div> <br /><br /></body><br /><br /></html><br /><br /><br /></pre><br /><br /><br />The main things I want to point out here are:<br /><br />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.<br /><br />2. in the mouse click function (<span style="font-weight:bold;">foiClick</span>), 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().<br /><br />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.<br /><br />That's all for this post.<br /><br />-LJUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-84078003938825237822011-07-25T10:55:00.002-04:002011-07-25T10:59:27.605-04:00iOS support in Oracle Maps APIWith the latest patch release (version<span style="font-size:100%;"><span style="font-weight: normal;">11.1.1.5.1 found <a href="http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html">here</a></span></span><a href="http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html"> </a>), 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.<br /><br />In addition to the iOS support, we are also looking into Android support in the future.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-87215953753309561062011-07-18T19:28:00.010-04:002011-07-18T20:13:10.803-04:00Deploying MapViewer on IBM WebSphere 7I just finished deploying MapViewer (the 11.1.1.5.1 patch release found <a href="http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html">here </a>) 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.<br /><br />1. Log into WebSphere console, and pick the server instance to deploy MapViewer.<br /><br />2. Start deploying MapViewer by creating a new enterprise application.<br /><br />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.<br /><br />4. Go through the necessary steps by accepting all the defaults as instructed, but note the following special instructions.<br /><br /> At step 7 "<span style="font-weight: bold; color: rgb(255, 0, 0);">Map context roots for web modules</span>", make sure the context root is set to "/mapviewer".<br /><br />Then at Step 8 "<span style="font-weight: bold; color: rgb(255, 0, 0);">Map security roles to users or groups</span>", make sure the admin user (<span style="color: rgb(255, 0, 0);">virtuser</span> in my case) is mapped to the <span style="color: rgb(204, 0, 0);">map_admin_role</span> 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.<br /><br />5. You should get a summery page like below at the end of the deployment steps.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-m5LiblDQzKU/TiTEMLgio4I/AAAAAAAAAHs/ML0IdF3vYwU/s1600/Image14.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 163px;" src="http://1.bp.blogspot.com/-m5LiblDQzKU/TiTEMLgio4I/AAAAAAAAAHs/ML0IdF3vYwU/s320/Image14.png" alt="" id="BLOGGER_PHOTO_ID_5630841147646714754" border="0" /></a><br /><br />Now save the configuration and finish the deployment process. You should see MapViewer in the applications list, as illustrated below.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-L989e_D4OXo/TiTE9YIiASI/AAAAAAAAAH0/hOdqxTygubc/s1600/Image16.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 163px;" src="http://2.bp.blogspot.com/-L989e_D4OXo/TiTE9YIiASI/AAAAAAAAAH0/hOdqxTygubc/s320/Image16.png" alt="" id="BLOGGER_PHOTO_ID_5630841992849260834" border="0" /></a><br /><br />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 <span style="font-weight: bold;">Management</span> tab, then <span style="font-weight: bold;">Configuration</span>. 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:<br /><br /><span style="color: rgb(102, 0, 0);">/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/AppSrv01_Cell01/OracleAS MapViewer.ear/web.war/WEB-INF/conf/mapViewerConfig.xml</span><br /><br />This tells us that WebSphere has expanded the mapviewer.ear file into the directory:<br /><br /><span style="color: rgb(102, 0, 0);">/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/AppSrv01_Cell01/OracleAS MapViewer.ear/</span>.<br /><br />7. Now, we need to modify MapViewer's libraries in order for it to work properly in WebSphere 7.<br /><br />8. Go to MapViewer's web.war/WEB-INF/lib folder, and physically remove the two jars: <span style="color: rgb(255, 0, 0);">jsf-api.jar</span> and <span style="color: rgb(255, 0, 0);">jsf-impl.jar</span>. 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.<br /><br />9. From your Oracle 11g database install, copy the two JDBC driver related jars, <span style="color: rgb(204, 0, 0);">ojdbc5.jar</span> and <span style="color: rgb(204, 0, 0);">orai18n.jar</span>, 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.<br /><br />10. Now, go to WebSphere console and restart the MapViewer application.<br /><br />From this point on, you will just need to perform typical MapViewer configuration tasks such as adding a new data source et al.<br /><br />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).Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-78806247043302795852010-10-08T10:12:00.004-04:002010-10-08T10:18:44.900-04:00Sending command-line admin requests to MapViewerAs you already know, MapViewer has several web pages where you can (after logging in) perform various admin tasks using XML requests. These tasks range from managing mapviewer's metadata cache, data sources, to tile layer pre-fetching.<br /><br />Sometimes one may have the need to perform these tasks from a command line or script. This is especially helpful if you need to automate certain aspects of managing a MapViewer instance (such as periodically clearing its tile layer cache or metadata cache).<br /><br />A while back we uploaded a simple tool that enables just that. If you are interested, please go to MapViewer's download page on OTN:<br /><br /><a href="http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html">http://www.oracle.com/technetwork/middleware/mapviewer/downloads/index.html</a><br /><br />and look for the <strong>Oracle Fusion Middleware MapViewer Admin Tool</strong>. It comes with a detailed readme describing how to use this tool to send admin requests to MapViewer server from a command line or from a script.<br /><br />Basically this tool allows you to specify the user name and password for the MapViewer admin URLs, and a XML document containing the admin request itself. It will then authenticate to the MapViewer and post the request doc to the server for processing.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-60736351365047131132010-09-14T12:08:00.006-04:002010-09-14T13:22:54.364-04:00MapViewer performance tuning tips - part 4In this post we will discuss best practices that deal with overall MapViewer deployment and configuration. We will also briefly touch base on how to monitor a running MapViewer instance to find troubling themes.<br /><br /><span style="font-size:130%;">Deployment and Configuration</span><br /><br />MapViewer is a J2EE application that runs in all modern J2EE containers. Deploying MapViewer is no different from deploying other J2EE applications.<br /><br />Ideally MapViewer should be deployed to a dedicated JVM. In Oracle iAS world, this will be a dedicated OC4J instance, and in the WebLogic Server (WLS) world, this will be a dedicated server in a domain.<br /><br />The reason is simple, MapViewer, while having a small foot print itself, often requires large amount of memory and CPU resources at run time depending on the work load. So it is best to deploy MapViewer to a JVM instance that runs only MapViewer (and minimum amount of other J2EE supporting services), so that unnecessary contentions or even interruptions with other applications can be minimized. It will also be easier to monitor MapViewer's performance when it is the only application running in the JVM.<br /><br />Note however there is nothing inherently wrong to deploy and run MapViewer with other J2EE applications in a shared JVM.<br /><br /><br /><span style="font-weight: bold;">JVM heap size</span><br /><br />One of the key factors that will affect mapViewer performance is the amount of Heap memory allocated to the JVM. A minimum of 512 MB is recommended. On 32 bit operating systems, the maxium heap memory should not exceed 1.5GB (or 1500 MB). A typical MapViewer install will run happily with 1GB of heap memory.<br /><br />You set heap memory via JVM's -Xmx option.<br /><br />Another important memory allocation parameter is the young generation size within the JVM. Young generation is a pool of memory reserved for short-lived objects. A typical map request will result in MapViewer creating many such objects (for instance, to represent geographic features in memory), so a sufficiently large young generation within the heap is crucial in preventing the JVM spending too much time on garbage collection.<br /><br />The young generation size can be set via the JVM parameter:<br />-XX:newSize=80M<br />and<br />-XX:maxNewSize=200M<br /><br />The first parameter specifies a starting young generation size of 80MB, while the second parameter indicates a maximum young generation size of 200M.<br /><br />Typically the young generation size should not be more than 10 to 20 percent of the total heap size.<br /><br /><br /><span style="font-weight: bold;">Spatial data cache</span><br />MapViewer lets you optionally configure an in-memory geometry data cache via the "spatial_data_cache" tag in mapViewerConfig.xml. This cache is used to buffer geometry features generated for themes whose caching mode is either set to ALL or NORMAL. (Note that you set a theme's caching mode in Map Builder's theme editor, in the Advanced tab).<br /><br />When a theme's caching mode is set to ALL, MapViewer will load all of its features upon first request, and store the data in the cache. It also creates an in-memory R-Tree index on the features. All subsequent requests for this theme will be satisfied out of this cache, with no trips to the database.<br /><br />When a theme's caching mode is set to NORMAL, MapViewer will store the theme's features as they are loaded. Note that MapViewer still queries the database every time such a theme is requested, but, in the event a feature is already in the cache, the un-marshaling or parsing of the database formatted geometry object is skipped, and the corresponding Java geometry object is reused out of the cache.<br /><br />Our recommendation regarding theme caching, is to use caching mode ALL for small amount of themes that are based on small to medium sized tables (with couple hundred to tens of thousands of features) with static contents. And <span style="font-weight: bold;">turn off NORMAL caching</span> for all other themes. In other words, a pre-defined geometry theme should have its cache mode set to either NONE or (in rare cases) ALL.<br /><br />The reason we do not recommend using the NORMAL caching mode is that it does not save much resource or time, in fact, it makes memory usage go up without much benefit at all. We could even argue that if too many theme features are cached the JVM may start doing more and more garbage collections which can adversely affect performance.<br /><br />It is especially important to turn themes' caching off (by setting caching mode to NONE) before you start a tile pre-fetching task. During a tile prefetching, large amount of map requests will be sent to the MapViewer, and any cached geometries will soon become out dated, or rather, out of the region of interest.<br /><br />Alternatively, prior to a large tile prefetching task, you can simply set the spatial data cache's max_cache_size to 0, which then automatically disables the caching of any theme's features.<br /><br />We recommend the spatial_data_cache to have a max size of no more than 200MB (on a 32 bit OS), or 15 percent of total heap memory. In fact, we often found a performance boost by simply turning this cache off (setting its max size to zero)!<br /><br />Note that when you have themes with caching mode ALL, mapViewer may not be able to fit all of its data in the cache, in which case it automatically switches the theme's cache mode to NORMAL (which as we mentioned earlier is not very ideal). So you need to carefully monitor any exception or error messages in the MapViewer log files to see if it failed to load all the data for themes with caching mode ALL. In the event this happens, you should simply set the theme's cache mode to NONE.<br /><br />Note further that this internal memory cache will likely undergo major changes in MapViewer 11g R2 to truly boost performance.<br /><br /><br /><span style="font-weight: bold;">Monitoring theme processing time</span><br />When you notice a slow map response time, the first thing you do is open the URL /mapviewer/admin.html, and check for slow themes.<br /><br />This URL is only available in MapViewer version 11g R1 and later. It will require admin log in. Once logged in, you will see the Top Theme Queries text field, which you can submit to check which theme(s) are taking the most time to process. This can be very useful in quickly catching themes that are taking too long to return data from the database (indicating either a database performance issue, or a badly defined theme), or are returning too many rows/features, or both.<br /><br />You can use the Reset Top Theme Queries form to wipe out existing top theme statistics, and MapViewer will automatically start collecting new stats for future map requests. This is useful if you have made changes to some themes and want to see if they are still the top (bad) themes.<br /><br /><br />You can also use the same URL to check the status of your MapViewer, such as how many active DB connections/sessions are being used currently.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-7628875492747705702010-05-19T15:26:00.003-04:002010-05-19T15:43:31.706-04:00new public APIs for GeoCoding & RoutingSome of you probably already know or are using various XML APIs to interact with our hosted LBS service at elocation.oracle.com. These XML APIs can be used to geocode your street addresses and get driving directions between two addresses, and also to get maps.<br /><br />Recently we have published a new set of simple JavaScript APIs for geocoding and routing. These APIs, or rather JavaScript libraries, are hosted on the same public elocation.oracle.com server, and are very easy to use from your HTML/AJAX applications.<br /><br />You can find more details about the new GeoCoding and Routing APIs in a presentation given during the Oracle Spatial User Conference held in Phoneix, Arizona last month. Please download the presentation here:<br /><br /><a href="http://download.oracle.com/otndocs/products/spatial/pdf/osuc2010_presentations/osuc2010_geocoder_sravada.pdf">http://download.oracle.com/otndocs/products/spatial/pdf/osuc2010_presentations/osuc2010_geocoder_sravada.pdf</a><br /><br />The presentation itself actually covers a lot of ground on Spatial's geocoding and routing capabilities. The new JS APIs and sample codes start from page 78.<br /><br /><br />For more presentations on both Spatial and MapViewer from this user conference (which was a smashing success), visit here:<br /><a href="http://www.oracle.com/technology/products/spatial/htdocs/spatial_conf_1004_idx.html">http://www.oracle.com/technology/products/spatial/htdocs/spatial_conf_1004_idx.html</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-4146174737357043892010-03-25T14:20:00.002-04:002010-03-25T14:35:00.109-04:00Out of memory when pre-fetching tiles on Linux?If you suspect that your MapViewer instance is having memory related issues when pre-fetching large number of map tiles for a tile layer, and your OS is Linux, then maybe this tip will help you.<br /><br />Basically on Linux, the underlying file system itself will often aggressively use memory to cache file handles et al. When you start a large tile pre-fetching task, it is not uncommon for MapViewer to create hundreds of thousands of files (map tile images) in a short period. If the OS keeps caching these file system related "things" in memory, sooner or later your system will experience memory shortages, and this may cause MapViewer instance's JVM to crash or throw OutOfMemory exceptions.<br /><br />Fortunately there is an easy workaround (thanks to Ji who found and tested it). All you (or your system admin) need to do is execute the following shell command as root:<br /><br /><span style="font-weight: bold;">#> sync; echo 3 > /proc/sys/vm/drop_caches</span><br /><br />This command will force the Linux kernel to release file system related caches. It is best to run this script periodically (by using a cron job) like every 3 hours.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-43951010921991021352010-02-03T14:24:00.018-05:002010-02-03T15:02:49.735-05:00MapViewer performance tuning tips - part 3<span style="font-weight: bold;font-size:130%;" >Middletier (MapViewer) side of things</span><br /><br />Lets now look at various factors within MapViewer itself that may affect overall performance. There are also settings in the J2EE container level that can affect both performance and scalability, which we will also touch upon later.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Types of map requests</span></span><br /><br />In order to properly tune MapViewer performance and size your hardware for deployment, you need to first understand where and how MapViewer spends its resources. Because MapViewer resources are primarily spent on processing map requests, it is critical to understand the types of requests that MapViewer may receive.<br /><br /><span style="font-weight: bold;">XML map request</span><br /><br />The most basic type of request is simply a single XML document containing a complete map request posted to a MapViewer server’s URL directly. In this request doc, you can specify a base map, one or more additional themes (pre-defined or dynamic), a map query window, and a response format, among many other things. When MapViewer receives such a request, it breaks down the basemap (if specified) into a list of composing themes, and then adds those additional themes to form a final theme list. It then queries and fetches data for all the themes on the list, rendering their data into one or more images. The result images are either directly streamed back to the client, or saved to the disk (in which case it is the URLs to the saved image files that are sent back to the client).<br /><br /><span style="font-weight: bold;">WMS requests</span><br /><br />MapViewer can also act as a WMS (Web Mapping Service) server. When it receives an incoming WMS request, the request is first converted into an XML map request, followed by the same workflow as if the client had just sent the XML request directly.<br /><br /><span style="font-weight: bold;">Oracle Maps requests</span><br /><br />With the Oracle Maps JavaScript API, a typical “map” displayed by your application is often composed of one or more map tile layers, plus one or more Feature Of Interest (FOI) layers. Whenever such a map is displayed or refreshed, the Mapviewer server will receive one FOI request for each visible FOI layer, plus multiple map tile image requests.<br /><br />For each FOI request, you can think of it as a simplified XML map request containing just a single theme. Once the features of this theme are loaded, MapViewer can either render them into individual FOI images (one small image for each feature), or combine all the features into a single image equal to the size of the application map window (when the whole-image option is enabled on the FOI layer).<br /><br />For each map tile request, if the tile (an image file stored on the server) does not already exist, MapViewer will need to generate it on the fly, by issuing itself an XML map request that contains just the name of the base map of the tile layer. The query window of this XML map request will be the data coverage area for this particular tile. The normal workflow then follows, and the result image is always stored to a specific folder on the server. It then serves this tile image file to the client.<br /><br />Note that once a map tile is generated and saved, all subsequent requests to that tile can be fulfilled extremely quickly, because MapViewer no longer needs to process/render it. Serving 100s of tile images per second is a typical performance. Whether your browser can load and display that many images quickly enough however is another matter and depends on such factors as your network connection speed.<br /><br />Because on the fly rendering of map tiles is expensive, you should consider tile pre-fetching by issuing an admin request to MapViewer when it is not under load (or on a non-production server). When MapViewer receives a pre-fetching request, it simply issues many concurrent map tile requests to itself, which are basically XML map requests as mentioned earlier.<br /><br /><span style="font-weight: bold;">JavaBean API requests</span><br /><br />If your application uses the JavaBean API of MapViewer, what happens is that as soon as you call oracle.lbs.mapclient.MapViewer’s run, pan or zoom method, it will construct a XML request document based on the information you have provided (name of basemap, themes you added, et al), and send it to the MapViewer server for processing.<br /><br /><span style="font-weight: bold;">In the end it's all XML</span><br /><br />So as you can see, no matter which API your application uses, all that the MapViewer rendering engine sees are XML map request docs. From now on we will shorten the verbose “XML map request doc” to just “map request”. Note that client side map actions (clicking, zooming, panning et al) may or may not result in a map request to the server. And sometimes one action on the client side may even lead to multiple map requests (such as when zooming an Oracle Maps map with multiple visible FOI layers).<br /><br />While the structure of MapViewer’s XML map request document can be very complex (the DTD for which can be found in the MapViewer User Guide), for simplicity we can think of it simply as a flat list of themes that MapViewer needs to process. Sometimes this list contains just one theme, and yet other times it may contain dozens or even hundreds of themes.<br /><br />Given the above understanding, let’s now look at how MapViewer processes the themes for a single map request.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Rendering themes of a map request</span></span><br /><br />When MapViewer processes a theme, it begins by issuing a query to the database to load the data for that theme (for Spatial based themes anyway). This query typically contains a spatial filter so that it only fetches data within the current viewing window. In the first two posts we have already covered how to speed up this phase by reducing the database time.<br /><br />Note that the rendering phase does not actually start until all the themes’ loading phases have completed. In other words, if your map request contains 10 themes, the rendering phase will not start until all 10 themes have finished loading their data from the database. In other words, <span style="font-weight: bold;">all the data for all the themes will be held in memory until the map request itself is completed</span>. This is why it is important to consciously limit the number of features MapViewer might load for any given theme. When a map request is completed (the final image rendered and saved or streamed back to the client), then all the loaded theme data and temporary shapes et al. are released from memory.<br /><br />During the actual rendering process, MapViewer iterates through all the loaded features of each theme, converting each geometry object from its raw database format into a Java representation when necessary, followed by the creation of a Java2D shape or point. Any necessary viewport transformation is also carried out at this stage.<br /><br />If a theme requires text annotation, then the labeling process occurs after all the themes have completed the shape-rendering phase. Note that rendering follows the order of themes as they are listed in the map request, but for labeling the order is actually reversed. In other words, the last theme in the list is always labeled first.<br /><br />To summarize, the total time (excluding the database time) MapViewer spends on processing a single map request is affected by the following factors, roughly in decreasing order of significance:<br /><br /><ul><li>The number of features loaded by each theme, and total number of features loaded.<br /></li><li>The cost of rendering and labeling a single feature; this is in turn dictated by how complex each rendering and labeling style is, how detailed (in terms of number of vertices) are the geometries on average, et al.</li><li>The raw speed of the server’s disk, CPU and memory access</li><li>Whether anti-aliasing is requested</li><li>The amount of heap memory allocated to MapViewer</li><li>The version of JDK being used</li></ul><br />Note that the first item (number of total features loaded) also has the biggest impact on MapViewer’s memory usage.<br /><br />While understanding how MapViewer works on a single map request certainly helps, in a real world scenario your MapViewer instance is often flooded with many concurrent map requests initiated by a variety of applications and clients using different APIs. In order to improve the scalability of MapViewer and properly size its hardware platform, one needs to understand how MapViewer handles concurrent map requests. This is discussed next.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Database sessions, number of mappers and concurrent map requests</span></span><br /><br />Prior to MapViewer version 10.1.3.3, themes in a single map request load their data in parallel. In other words, if a map request is composed of 10 themes, then 10 database connections are obtained right off the bat, each executing the query of one theme. This “liberal” usage of database sessions often leads to scalability issues while providing marginal if any performance gain.<br /><br />Starting with MapViewer version 10.1.3.3, SQL execution of themes’ queries are carried out in a serial fashion within each map request. A theme cannot start loading its data until the theme before it in the list has finished its query execution and data loading. The end result is that only one database connection is ever needed when processing a map request, no matter how many themes may be involved.<br /><br />For a given data source, the maximum number of concurrent map requests MapViewer will accept is determined by the number of mappers specified for that data source. In other words, if a data source’s <span style="font-style: italic; font-weight: bold;">number_of_mapper</span> attribute is set to 10 (in the MapViewer config file), then a maximum of 10 concurrent map requests can be processed (for that data source) at any given time. Because each map request will use one database connection, there can be a maximum of 10 active database sessions for the data source schema. When the 11th map request arrives it must wait in the queue until a free mapper becomes available.<br /><br />You may recall that in MapViewer’s data source definition, there is also a <span style="font-style: italic;">max_connection </span>parameter. Starting with version 10.1.3.3, this parameter is no longer needed actually. This is because the maximum number of connections out there for a given data source is always bound by the <span style="font-weight: bold; font-style: italic;">number_of_mapper </span>parameter.<br /><br />Understanding the above, you may come to the conclusion that in order to increase the scalability you simply increase the number of mappers specified for a data source. The problem is that as you increase this number, you are also increasing the number of potential concurrent database sessions, the memory usage inside MapViewer and the amount of raw data it needs to push through its rendering pipeline. Finally, if you have multiple data sources defined, then the total concurrent map requests that can potentially arrive at the MapViewer is the sum of all the data sources' maximum concurrent requests.<br /><br />In the end, it is difficult to provide a clear-cut formula for determining what level of hardware you will need for your MapViewer instances. For instance, to determine roughly how much heap memory you need to allocate to a MapViewer instance, you need to look through each defined data source, finding out the average number of features each theme will load into memory and their geometric complexity, the number of themes in a typical map request, and the maximum concurrent map requests you wish to sustain. You also need to factor in things such as the in-memory geometry cache which are permanent. The best approach is to simply perform load tests against your application and monitor various logs and stats from your database and MapViewer instances to see if they are being saturated.<br /><br />In the next post we will dig in further and provide a number of practical tips on tuning MapViewer performance.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-85917245593067386522010-01-14T16:25:00.012-05:002010-01-21T09:57:29.519-05:00MapViewer performance tuning tips - part 2This is the second post of the performance tuning tips series.<span style="font-weight: bold;"><br /><br /></span><ul><li><span style="font-weight: bold;">Finding bottlenecks in your Oracle database</span></li></ul><br />When you identify a theme with an unusually high "database time", it's time to look for database fixes. While typical database query optimization tips and tricks still apply, spatial queries have some unique characteristics, especially when the base table of your 'troubling' theme contains a large number of rows.<br />From my own observations over the years, in many cases the "database time" of a MapViewer theme is actually database idle time or wait time. To be more specific, it is time the database spent waiting on disk I/Os. This is probably nothing shocking given that many MapViewer theme queries can fetch a lot of data in terms of pure volume (as measured in total bytes), especially when polygon or polyline type geometries are involved. Compared with a theme query, your typical shopping cart query that fetches a product listing is almost negligible as far as result data volume is concerned. With a huge base table, chances are the database buffer cannot easily cache all the data, so it often needs to read physical disk blocks in order to fetch and return data for a query.<br /><br />When diagnosing database bottlenecks such as disk I/O waits , there are two powerful tools that come with Oracle database 10g and later versions. They are <span style="font-weight: bold;">AWR </span>(Advanced Workload Repository) and <span style="font-weight: bold;">ADDM</span> (Automated Database Diagnostic Monitor). I found them invaluable in finding out why your MapViewer application is running slow, as they can not only identify I/O bottlenecks, but also many other kind of bottlenecks in the database. Note however they do not replace other tuning tools such SQL Tuning Adviser. In fact ADDM will often suggest you run SQL Tuning Adviser on specific SQL queries it deemed problematic.<br /><br />Let's jump right into action already. The following are the basic steps of using these two tools.<br /><br /><span style="font-weight: bold;">Step 1 </span> Login as DBA, then create a "before" snapshot of the database:<br /> SQL> exec dbms_workload_repository.create_snapshot;<br /><br /><span style="font-weight: bold;">Step 2 </span>Run your MapViewer application load tests. When done,<br /><br /><span style="font-weight: bold;">Step 3 </span>Create an "after" snapshot of the database, using the same command:<br /> SQL> exec dbms_workload_repository.create_snapshot;<br /><br />With these two snapshots, you can now execute the AWR and ADDM scripts to generate very informative and detailed reports on what happened inside the database during these two snapshots. Keep in mind that the stats gathered by AWR and ADDM cover all database activities for all sessions, not just sessions created by MapViewer to perform theme queries.<br /><br /><span style="font-weight: bold;">Step 4 </span> Generate an AWR report.<br />To create an AWR report, execute the following as DBA:<br /><br />SQL> @$ORACLE_HOME/rdbms/admin/awrrpti.sql<br /><br />When prompted, use HTML as the report format, and pick the two snapshots that you just created.<br /><br />After exiting SQL*Plus, you will see an HTML file containing the AWR report. Open it in your browser, and you will be greeted with a rich set of database activity reports.<br />One of the interesting tables is titled "Top 5 Timed Foreground Events". For instance, this is the result from a recent AWR report generated for my spatial database:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vMku6FYL_58/S0_M-pK66PI/AAAAAAAAAG8/PLr7YN5KItk/s1600-h/awr-events.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 130px;" src="http://2.bp.blogspot.com/_vMku6FYL_58/S0_M-pK66PI/AAAAAAAAAG8/PLr7YN5KItk/s320/awr-events.png" alt="" id="BLOGGER_PHOTO_ID_5426781452580350194" border="0" /></a><br /><br />As you can see, it shows that the database spent a whopping 96.55% of time waiting for User I/Os (db file sequential reads) ! You can also check out several other tables such as "SQL ordered by Elapsed Time" and "SQL ordered by User I/O Wait Time" et al. It is also quite easy to find out which SQL is causing the most User I/Os, so on and so forth. Of course, your report may not show user I/O as an issue, but you get the idea.<br /><br />While AWR is very useful in providing you with a detailed break down of the database events and timings, it is best complemented by the adviser tool, ADDM, which reads off the same set of stats between the two snapshots, but can provide you with concrete advices on how to fix the bottlenecks in your database.<br /><br /><span style="font-weight: bold;">Step 5 </span>Generate an ADDM report.<br /><br />While you can always use EM to view the ADDM report, here we just want to generate a simple text report using SQL*Plus by running the following command as DBA:<br /><br />SQL> @$ORACLE_HOME/rdbms/admin/addmrpt.sql;<br /><br />Again this script will prompt you for the before and after snapshots' IDs. Then it generates a .lst file which you can open with any text editor. In this text report you can find some very insightful suggestions. For instance, in one of my reports it detected that the disk containing the database data file of a large theme's base table has a below-average I/O speed, and suggested file striping as one way to reduce I/O waits. This is exactly the kind of advices that can immediately provide a performance boost.<br /><br />While I have been stressing the negative impact of heavy user I/Os, please note that your situation may very well be a different one. For instance you may not have an I/O bottleneck at all, so please be open minded when reading these two reports and be prepared to wrestle with other kind of issues within your database.<br /><br /><br /><ul><li><span style="font-weight: bold;">Reorganizing your large tables</span></li></ul><br />Let's say you indeed find yourself in a similar situation where you see a lot of User I/O wait events, especially on your large tables (those with hundreds of thousands or millions of rows). Then how do you tackle this issue? One of the most obvious remedies is to partition both your data tables and associated spatial indexes, if they are not already partitioned.<br /><br />The other tip, which will be described in detail now, is to reorganize the table rows based on the proximity of the geometry column. The basic idea is to store rows in neighboring database blocks if their geometries are close to each other spatially. When stored this way, rows that are to be returned for a theme query will more likely be found in neighboring data blocks on the disk, thus significantly reducing disk reads. This re-org will help most spatial queries with predicates such as SDO_FILTER or SDO_RELATE. MapViewer for instance always uses SDO_FILTER for normal map panning/zooming and WMS type map requests, thus can benefit from such a table wide re-org, sometimes tremendously.<br /><br />Lets first see what happens if you do not reorganize your table. Lets say each disk block has capacity for 100 rows. In a ‘uniform but random storage’ case, for any given query window, each "hit" block may only have 10 rows that are within this window. Now lets say a particular map request’s query window interacts with 1000 rows according to the spatial index. Assuming the table is so big and the incoming query windows change so often that the database data buffer is basically useless. What the database will end up doing then is reading 100 blocks from the disk in order to fetch these 1000 rows based on their ROWIDs produced by the spatial index. Reading so many blocks for a single query is very expensive. Now imagine 20 concurrent incoming map requests, each having a different viewport, and you can easily imagine why the database spends majority of its time waiting for disk reads. As a result, the overall throughput of MapViewer plummets.<br /><br /><br /><ul><li><span style="font-weight: bold;">Script for Reorganizing a large table</span></li></ul><br />So how do you reorganize row storage? The following script is actually documented in the “Pro Oracle Spatial for Oracle Database 11g” book, Chapter 16. It uses a linear tessellation key to re-order the geometries stored in a table. For those of you don’t have access to this book, here are the (slightly modified to fix several typos in the book) scripts you can copy and use.<br /><br />First, create a package in the MDSYS schema (it won't work in any other database schema!) :<br /><br />CREATE OR REPLACE PACKAGE clusterit<br />AS<br /><br />FUNCTION linear_key(location sdo_geometry, diminfo sdo_dim_array)<br /> RETURN RAW deterministic;<br />END;<br />/<br /><br />CREATE OR REPLACE PACKAGE BODY clusterit<br />AS<br />FUNCTION linear_key<br />(<br />location sdo_geometry,<br />diminfo sdo_dim_array<br />)<br />return RAW deterministic<br />AS<br />ctr sdo_geometry;<br />rval raw(48);<br />lvl integer;<br />BEGIN<br />ctr := sdo_geom.sdo_pointonsurface(location, diminfo);<br />lvl := 8;<br />rval:=<br /> MD.HHENCODE(<br /> ctr.sdo_point.x, diminfo(1).sdo_lb, diminfo(1).sdo_ub, lvl,<br /> ctr.sdo_point.y, diminfo(2).sdo_lb, diminfo(2).sdo_ub, lvl);<br />return rval;<br />END;<br /><br />END;<br />/<br /><br />Next, log into the proper schema, and make a backup copy of the problem base table ‘<span style="font-style: italic;">my_table</span>’ (drop its spatial index first):<br /><br />SQL> rename my_table to my_table_dup;<br /><br />Add a linear key column:<br /><br />SQL> alter table my_table_dup add (linear_key raw);<br /><br />Then pre-compute and store the linear keys:<br /><br />SQL> update my_table_dup a set linear_key =<br />mdsys.clusterit.linear_key(a.geometry,<br />(select diminfo from user_sdo_geom_metadata where table_name='MY_TABLE’ and column_name='GEOMETRY'));<br /><br />Finally, re-create the original table with proper storage order:<br /><br />SQL> create table my_table as select * from my_table_dup where rownum <1;<br />SQL> insert into my_table select * from my_table_dup order by linear_key;<br />SQL> commit;<br />SQL> drop table my_table_dup;<br /><br />Don’t forget to recreate the spatial index on <span style="font-style: italic;">my_table</span>.<br /><br />Now re-run your MapViewer tests and see if this reorganization has helped its overall performance. In one internal and not so rigorous experiment, after reorganizing a large table using the above approach, we observed as much as 300% increase in overall MapViewer throughput.<br /><br />In summary, AWR and ADDM are two of the more useful tools at your disposal when diagnosing high database times, and pay special attention to excessive database reads. This blog also assumes that your typical MapViewer theme is a pre-defined geometry theme with relatively simple query conditions. If your theme uses super complex dynamic SQL queries, then chances are you have more than disk reads to worry about. In any case, database tuning in general, and Spatial SQL tuning in particular, is a very deep topic in itself, and I'm really in no position to offer any authoritative advice; so please don't blame me if my little tip above did not actually reduce your database time :)Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6774903665752106951.post-66071166347022112572010-01-13T22:31:00.006-05:002010-01-14T22:44:53.550-05:00MapViewer performance tuning tips - Part 1This is the first of a series of blogs on MapViewer performance tuning.<br /><br /><span style="font-weight: bold;">Overview </span><br /><br />When your MapViewer application performs poorly, there are many possible causes. Maybe your application is trying to (unnecessarily) display way too many features on a map or layer. Maybe your database query (for dynamic themes) is too complicated and poorly optimized. Or maybe the database is doing too many disk I/Os when fetching the result set for a theme. It could also be due to a poorly configured MapViewer in-memory cache, an overwhelmed J2EE container (overloaded with many other applications), or just a very slow middle-tier box. It could be all of the above. The symptom however is always the same: when a user clicks on the map to pan or zoom, she will wait a long time before the map completely refreshes itself.<br /><br />So how to find the true bottleneck? Where do you start when diagnosing a slow mapping application? The short answer, is to first identify the most time consuming theme(s) in your application, by looking at the log file.<br /><br />To do so set MapViewer's logging to the "finest" level, restart MapViewer, and run the application just long enough (or manually submit a single XML map request) to generate some meaningful logs. When scanning the freshly created MapViewer log file, for each theme you should see several log records like the following:<br /><br />FINER: [ THEME_DEMO_HIGHWAYS ] sql exec time: 585ms, total time <span style="font-weight: bold;">loading</span> 8 features: 2679ms.<br />FINER: time to <span style="font-weight: bold;">render</span> theme THEME_DEMO_HIGHWAYS with 8 styled features: 72ms<br />FINER: time to <span style="font-weight: bold;">label</span> theme THEME_DEMO_HIGHWAYS with 8 styled features: 112ms<br /><br />In the first log record, pay special attention to the last number, <span style="font-weight: bold;">2679ms</span>. This number (in milliseconds) indicates how long it took the database to execute the theme query, fetch result rows from data blocks, and transmit the result set over the network to MapViewer. For simplicity we will call this the "<span style="font-weight: bold;">database time</span>". Likewise let's call the combined rendering and labeling time indicated by the second and third log records the "<span style="font-weight: bold;">MapViewer time</span>"; after all that is how long MapViewer actually spent doing something useful instead of just waiting for and receiving data from the database.<br /><br />In many cases, the database time will be the dominant one, so you will need to poke around the database and speed things up there. We will get into it later.<br /><br />If the MapViewer time is high, we will need to find out why. One recommended approach is to run a CPU profiling of the MapViewer instance. Again we will provide more details in a later post.<br /><br />Reducing these two types of time will have a positive impact on your application's performance regardless of which MapViewer API you are using.<br /><br /><span style="color: rgb(0, 102, 0);">Note that starting with MapViewer 11g R1 there is another way to easily spot themes with excessive "database time". To do so you must first log in as the MapViewer</span><br /><span style="color: rgb(0, 102, 0);">admin user. Then manually open the /mapviewer/admin.html page in your browser. You will see a "Top theme queries" text area with a Submit button underneath it. Click on the submit button to see a list of top (database) time-consuming queries. It's a good idea to first click the "Reset top theme queries" button so that MapViewer clears any existing list of themes and starts gathering fresh stats for you. </span><br /><br />Sometimes you may find that all of your themes are loaded and rendered quickly, but your application still takes a long time to display the map. Let's simply call this the "<span style="font-weight: bold;">user time</span>", since it is the time a user spent staring at a spinning clock or progress bar. When the sum of the "database time" and "MapViewer time" accounts for only a small portion of the "user time", we suggest you use a FireFox addon called "FireBug" to find out what exactly is happening on the wire and in your browser. For instance, is your Oracle Maps application overwhelming the remote web server with too many HTTP requests for map tile and FOI images? Maybe you should look into using the Whole-Image option for your FOI layer(s) to avoid transmitting many small pieces from MapViewer to the client every time a user pans or zooms the map. We will provide more tips like this in a later blog as well.<br /><br />To be continued...Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6774903665752106951.post-66249755390951656902010-01-06T17:56:00.002-05:002010-01-13T23:05:43.318-05:00MapViewer 11g patch 1 (11.1.1.2) availableWe are pleased to announce the first patch of MapViewer 11g R1 release. This patch, officially versioned 11.1.1.2, includes many bug fixes and incremental enhancements.<br /><br />Please download the new patch <a href="http://www.oracle.com/technology/software/products/mapviewer/index.html">here</a>.<br /><br /><br />The release notes can be found <a href="http://www.oracle.com/technology/software/products/mapviewer/text_files/mapviewer1112_readme.txt">here</a>.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6774903665752106951.post-48495151494259331502009-11-12T10:13:00.005-05:002009-11-13T09:45:24.236-05:00Use Mapviewer to cache WMS maps as map tiles<div><i>Warning: Not all map services providers(WMS included) allow their maps to be cached by others. Before using MapViewer to cache maps served by any third party map services provider, you should consult the map services provider to make sure you're allowed to cache their maps.</i></div><div><br /></div>With the use of map source adapter, you can let MapViewer cache maps rendered by an external map services provider as map tiles and use them in your Oracle Maps application. <div><br /></div><div>A map source adapter is basically a Java class that is called by MapViewer to construct requests understood by the external map services provider. MapViewer calls the map source adapter to construct map requests, send them to the map services provider, fetch the maps and cache them as map tiles. Mapviewer is shipped with a map source adapter for WMS, which you can use to cache maps served by a WMS server. To better understand how the map source adapter works, you can take a look at the source code of the WMS adapter, which can be found at $mapviewer_deploy_home/web/WEB-INF/tileserver/mvadapter/mcsadapter/WMSAdapter.java.</div><div><br /></div><div>Here are the steps to create a map tile layer using the WMS adapter.</div><div><br /></div><div>1. Login MapViewer's web admin page.</div><div><br /></div><div>2. Enter the tile layer creation interface. Choose "External" when being asked for the the type of map source.</div><div><br /></div><div>3. On the tile layer creation page, you need to provide the configuration information for the map tile layer. Besides regular tile layer configuration options such as name, data source, coordinate system, zoom level definition and etc, you also need to provide the following information specific to an external map tile layer. </div><ul><li>Map service URL: The URL of the external map services provider. In the case of WMS, it should be the URL of the WMS server, e.g. <a class="moz-txt-link-freetext" href="http://www.myhost.com/mywms">http://www.myhost.com/mywms</a>. </li><li>Adapter class: The path of the WMS adapter class. It should be mcsadapter.WMSAdapter. </li><li>Jar file location: the full path of the file mvadapter.jar, which is under $mapviewer_deploy_home/web/WEB-INF/tileserver/mvadapter. </li><li>Check "Adapter properties". </li><li>Add WMS parameters(name and value) for your map requests. Example: </li></ul><br /><pre><br /> name value<br /> ----------- -----<br /> version 1.1.1<br /> srs EPSG:4326<br /> layers Countries,Borders<br /> format image/png <br /> transparent true <br /></pre><br /><div><div><span class="Apple-style-span" style="font-family:'courier new';"><span class="Apple-style-span" style=" ;font-family:Georgia, serif;">4. Click "Submit" to create the tile layer. </span></span></div></div>Ji Yanghttp://www.blogger.com/profile/16611289627942490400noreply@blogger.com2tag:blogger.com,1999:blog-6774903665752106951.post-8572551996563212302009-10-22T10:06:00.003-04:002009-10-22T10:34:19.628-04:00Google maps tiles in a MapViewer appEarlier this year I posted an <a href="http://oraclemaps.blogspot.com/2009/03/displaying-mapviewer-tile-layers-over.html">article </a>on how to display MapViewer generated tiles in a Google Maps application. In this post I will discuss how to display Google Maps tiles in a MapViewer/Oracle Maps application. <br /><br />Starting with MapViewer 11g Release 1, a built-in Google Maps tile layer class has been added to the MapViewer's JavaScript API. It is called MVGoogleTileLayer. Unfortunately it is not officially documented for 11g Release 1 (but will be in the upcoming patch and future releases). <br /><br />This API class is a thin wrapper of the official Google Maps API, and as such you will need to get your own Google Maps key for your application. <br /><br />The basic steps for displaying Google Maps in your Oracle Maps application are:<br /><br /><span style="font-weight:bold;">Step 1. Import the Google Maps JavaScript library</span><br /><br /> <script src="http://maps.google.com/maps?file=api&v=2&key=[your-Google-Maps-API-key]"<br /> type="text/javascript"></script><br /><br />Again you will need to get your own Google Maps key from Google and set it in the above script tag.<br /><br /><span style="font-weight:bold;">Step 2. Add a Google Maps tile layer to the MVMapView object</span><br /><br />mapview = new MVMapView(document.getElementById("map"), baseURL);<br />baseMap = new MVGoogleTileLayer() ;<br />mapview.addMapTileLayer(baseMap);<br /><br />That's all it takes to display a basic Google Maps map in your MapViewer application.<br /><br />You can also change the type of map you get from Google Maps. Here is an example:<br /><br />var mapType = G_HYBRID_MAP; <br />basemap.setMapType(mapType) ;<br /><br />Where basemap is a MVGoogleTileLayer instance. Note that G_HYBRID_MAP is a constant defined by the imported Google Maps API library and represents a hybrid Google Maps type. The full description for this method is:<br /><br /><span style="font-weight:bold;">setMapType(mapType)</span><br />This method sets the type of the map, which can be one of the following predefined Google Map types, G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP and G_PHYSICAL_MAP.<br /><br />The only other method defined on the MVGoogleTileLayer class is getMapType(), which returns the current map type of the Google Maps being displayed.<br /><br /><br />Finally, as part of your application cleanup, please call Google Maps' clean-up method GUnload() (such as in the HTML page's unload event listener).Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-6774903665752106951.post-65358273729620629322009-10-05T10:35:00.007-04:002009-10-05T11:56:31.150-04:00displaying table of longitude and latitude pointsWhile in most cases your location data are stored in an Oracle database as SDO_GEOMETRY type, sometimes you may have certain point data stored simply as two numeric columns in a table (as longitude/latitude for instance). So how can you display these points using MapViewer? In this article I will present one of the more elegant options, namely using function-based index.<br /><br />The overall steps are:<br />1. Create a database function that returns a SDO_GEOMETRY object from two numeric values.<br /><br />2. Treat this function as a SDO_GEOMETRY column by creating an entry in the USER_SDO_GEOM_METADATA view.<br /><br />3. Create a Spatial index on this function<br /><br />4. Create a pre-defined theme in Map Builder for this function.<br /><br />5. Profit.<br /><br />Lets say we have an existing table CITIES in the schema SCOTT.<br /><br />SQL> desc cities;<br /> Name Null? Type<br /> ------------------------------- -------- ----------------------------<br /> ID NUMBER<br /> NAME VARCHAR2(100)<br /> ALIASE VARCHAR2(500)<br /> COUNTR VARCHAR2(100)<br /> POP NUMBER<br /> LON NUMBER<br /> LAT NUMBER<br /><br /><br />Where the two columns LON and LAT represent each city's location.<br /><br />So the first step is to create a function that generates an actual SDO_GEOMETRY object when supplied with a pair of (lon, lat).<br /><br />Step 1. Create function<br /><br />Execute the following while logged in as SCOTT:<br /><br />create or replace function get_geometry(lon in number, <br /> lat in number)<br />return SDO_GEOMETRY <span style="font-weight:bold;">deterministic </span>is<br />begin<br /> return sdo_geometry(2001, 8307, sdo_point_type(lon, lat, NULL),NULL, NULL);<br />end;<br />/<br /><br /><br />Note that the function must be deterministic.<br /><br />Step 2. Populate Spatial metadata view<br /><br />Now that we have a function, we need to make Spatial and MapViewer treat it as if it's a real SDO_GEOMETRY column. All we need to do is insert an entry for this function in the USER_SDO_GEOM_METADATA view. Again execute the following as SCOTT:<br /><br />insert into user_sdo_geom_metadata values('CITIES',<br /> 'scott.get_geometry(lon,lat)',<br /> sdo_dim_array(<br /> sdo_dim_element('Longitude', -180, 180, 0.005),<br /> sdo_dim_element('Latitude', -90, 90, 0.005)), <br /> 8307);<br /> <br />commit;<br /><br /><br />Step 3. Create a Spatial index:<br />We now need to create a Spatial index on the function, just like with any SDO_GEOMETRY columns. Without a Spatial index, your SQL spatial queries won't work, and MapViewer cannot display them easily.<br /><br />create index CITIES_SDX on <br /> CITIES(get_geometry(lon,lat))<br /> indextype is mdsys.spatial_index;<br /><br /><br />Step 4. Create a Map Builder theme<br /><br />Open Map Builder, click Show Data to open the data navigator. You should find the CITIES table under the user SCOTT. Right click it and choose "Create Geometry Theme". You should see that the function we just created is already picked up as the Spatial column, as illustrated in this screen shot:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vMku6FYL_58/SsoTKwl3eDI/AAAAAAAAAGY/1uolQCyztSg/s1600-h/func-index.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://3.bp.blogspot.com/_vMku6FYL_58/SsoTKwl3eDI/AAAAAAAAAGY/1uolQCyztSg/s320/func-index.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5389140979665565746" /></a><br /><br />Go through the normal process and complete the theme creation. You now have a pre-defined MapViewer theme that can be used to display those (X,Y) data. You can also add this theme to your AJAX map as a FoI (Feature Of Interest) layer.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-4066511295449251862009-09-18T16:09:00.015-04:002009-11-03T13:59:50.090-05:00Why am I getting "Request string is too long for Oracle Maps' non-AJAX remoting"?<div>You may get this error when your application is running in a web domain that is different from the one where mapviewer is running, e.g. your application is running on hostA and your MapViewer is running on hostB. Please note that different http ports on the same host are also two different domains. <div><div><br /></div><div>Oracle Maps client relies on AJAX to exchange data with the MapViewer server. In the scenario described above, when the client needs to send an AJAX request to the Mapviewer server, it is sending the request across domain, which is prohibited by all major web browsers. This is known as the cross-domain constraint. </div><div><br /></div><div>We implemented our own non-AJAX remoting mechanism to overcome this so that the Oracle Maps client can talk to the MapViewer in a different domain. This workaround has one limitation - the length of the non-AJAX remoting request can not exceed certain limit. If the requests are within the limit, everything will work great. That's why in most cases Oracle Maps application works fine across domain out of box. </div><div><br /></div><div>But things are not always that simple. If your application displays some complex theme based FOI layers, especially those with JDBC queries and/or dynamic styles, the underlying FOI requests might become too long to be handled by the non-AJAX remoting mechanism. As the result, you will get the error message mentioned in the title. </div><div><br /></div><div>To solve this problem, you have two options.<br /><br />Option 1</div><div>---------</div><div>Deploy a MapViewer to the same domain where your application is running. You don't have to configure this MapViewer to do any real mapping. You'll only need its proxy servlet, which can forward all requests from the client to the remote MapViewer that does the real mapping. The client will send all AJAX requests to the proxy servlet, which will then forward the requests to the remote MapViewer. Because the servlet is in the same domain as the application, there will be no cross-domain constraint when the client talks to the proxy. </div><div><br /></div><div>In your application code, you need to call MVMapView.enableXMLHTTP(true) at the beginning of your showMap function.<br /><br />function showMap()<br />{<br />MVMapView.enableXMLHTTP(true);<br />var baseURL = <a class="moz-txt-link-rfc2396E" href="http://oc4j-mv-domain/mapviewer">"http://hostB/mapviewer"</a>; </div><div>mapview = new MVMapView(mapDiv, baseURL) ;<br />...<br />}<br /><br /></div><div>Option 2</div><div>---------<br />Configure a reverse proxy in your HTTP server to forward requests sent to it to the remote MapViewer. This reverse proxy should accept requests sent to http://hostA<i class="moz-txt-slash"><span class="moz-txt-tag">/</span>mapviewer<span class="moz-txt-tag">/</span></i>* and forward them to <a class="moz-txt-link-freetext" href="http://remove-mapviewer:port/mapviewer/*">http://hostB/mapviewer/*</a>. If your HTTP server is Apache, then this can be done by adding the following two lines inside mod_proxy section in httpd.conf.</div><div><br /></div><div><div><IfModule mod_proxy.c></div><div> ProxyRequests Off</div><div><br /></div><div> <Directory proxy:*></div><div> Order deny,allow</div><div> Deny from 127.0.0.1</div><div> Allow from all</div><div> </Directory></div><div><br /></div><div><div><b><span class="Apple-style-span" style="color:#FF0000;"> ProxyPass /mapviewer/ http://hostB/mapviewer/</span></b></div><div><b><span class="Apple-style-span" style="color:#FF0000;"> ProxyPassReverse /mapviewer/ http://hostB/mapviewer/</span></b></div><div><br /></div></div><div><div></IfModule></div><div><br /></div><div><br /></div></div><div>Your application code should act as if the MapViewer is in the local domain, because the proxy is acting as a local MapViewer instance. For better performance, you should explicitly specify the remote tile server URL when creating a tile layer. By doing so, you're telling the Oracle Maps client to get the map tiles directly from the remote MapViewer, not via the proxy, which also means better performance.</div></div><div><br />function showMap()<br />{ </div><div>var baseURL = <a class="moz-txt-link-rfc2396E" href="http://www.blogger.com/post-edit.g?blogID=6774903665752106951&postID=406651129544925186">"http://"</a>+document.location.host+"/mapviewer" ;<br />mapview = new MVMapView(mapDiv, baseURL) ; </div><div>tileLayer = new MVMapTileLayer("myds.my_map", "http://hostB/mapviewer/mcserver"); </div><div>...<br />}<br /><br /><br /></div></div></div>Ji Yanghttp://www.blogger.com/profile/16611289627942490400noreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-50005659128509001442009-07-31T10:37:00.003-04:002009-07-31T10:41:38.479-04:00display labels with superscripts and subscriptsMy colleague Albert Godfrind just sent me a nice tip on how to display map labels containing subscripts and superscripts. Thought I will share it with you all.<br /><br />I found the following to work for me. I create a table (using a NVARCHAR2 column for storing the label), then I populate it with two rows: one using the standard label, one using the sub/superscript notation.<br /><br />create table labels (<br /> id number,<br /> label nvarchar2(30),<br /> geom sdo_geometry<br />);<br /><br />insert into labels (id, label, geom)<br />values (<br /> 1,<br /> 'm3 CH4 / min',<br /> sdo_geometry (2001, null, sdo_point_type (1,1,null), null, null)<br />);<br />insert into labels (id, label, geom)<br />values (<br /> 2,<br /> unistr('m\00B3 CH\2084 / min'),<br /> sdo_geometry (2001, null, sdo_point_type (1,2,null), null, null)<br />);<br />commit;<br /><br />insert into user_sdo_geom_metadata values (<br /> 'LABELS',<br /> 'GEOM',<br /> sdo_dim_array (<br /> sdo_dim_element ('x', 0, 100, 0.05),<br /> sdo_dim_element ('y', 0, 100, 0.05)<br /> ),<br /> null<br />);<br />commit;<br />create index labels_sx on labels (geom) indextype is mdsys.spatial_index;<br /><br />Mapviewer then nicely renders the super/sub scripts as illustrated!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vMku6FYL_58/SnMCOvXCYKI/AAAAAAAAAGQ/YmbudEdCQ3k/s1600-h/labels.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 253px; height: 193px;" src="http://2.bp.blogspot.com/_vMku6FYL_58/SnMCOvXCYKI/AAAAAAAAAGQ/YmbudEdCQ3k/s320/labels.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5364634033382908066" /></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-39511367013650849902009-07-28T15:32:00.003-04:002009-07-28T15:54:02.124-04:00Java API: setting array-type binding variables for a themeMapViewer supports pre-defined themes that contain query conditions with one or more binding variables. For instance, we can define a theme COUNTIES_BY_STATES that displays all the counties whose State abbreviations are in a list supplied by user at run time. <br /><br />The query condition for this theme may look like the following:<br /><br />( state_abrv in (select column_value from table(:1)) )<br /><br /><br />In other words, when this theme is to be displayed, it will require a list of State abbreviations such as 'CA', 'WA', 'NY' as the value for its query's binding variable. Note that this binding variable itself requires a SQL TABLE type.<br /><br />So how do you supply such an array of state abbreviation codes to the MapViewer from your Java application? The following shows the sample code that does just that.<br /><br /> String [] values = { "MA","NY","ME","NH" }; //list of state abbreviations<br /> ArrayParameter states = new ArrayParameter("MV_STRINGLIST",values);<br /> Object [] values = new Object[1]; //array containing all binding variable values<br /> values[0] = states;<br /> mapViewer.setThemeBindingParameters("COUNTIES_BY_STATES", values);<br /><br />Note that basically you must use MapViewer's public ArrayParameter class to supply the list of states (or list of any strings/numbers) for a single table-type binding variable. Because in this case there is only one binding variable in this theme's query, the values array contains only one element, the ArrayParameter instance.<br /><br />Note also MV_STRINGLIST is a SQL list/table type created by MapViewer automatically in each data source (database schema). Please check the 11g MapViewer user's guide on more information about this pre-created type.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-87528595376999408722009-07-28T15:09:00.002-04:002009-07-28T15:30:45.381-04:00multi-line labelsMapViewer supports labels or annotations that contain a newline char (ASCII char code 10). However by default such characters are ignored by MapViewer during the map text labeling process, and the label text appears in a single line (unless there is a text wrap width specified.)<br /><br />To force MapViewer to honor the newline chars in a theme's label texts, the theme must use a TEXT labeling style with the "Honor Newline" attribute set to true. This can be done from MapBuilder's TEXT style editor, by simply selecting the <span style="font-weight: bold;">Honor newline</span> check box. Now any theme that uses this TEXT style will automatically display any label text containing newline characters with multiple lines.<br /><br />If your application is written using the MapViewer Java API, and you need to add individual geo-features with multi-line text labels to your map, then additional caution must be taken when constructing the label text with the newline char. Namely, the label text for a feature must be constructed like this:<br /><br />String textLabel = "LINE 1" + "%26#10;" + "LINE 2";<br /><br />Typically in an XML document (the Java API eventually will convert your current map request into an XML request before sending it to the MapViewer server), one uses &#10; to represent the newline char(10). Because we are sending the entire map request string using HTTP POST from map client to the server, the character '&' itself must be escaped as '%26', hence the odd-looking string <span style="font-weight: bold;">%26#10;</span> representing an HTTP-safe newline character.<br /><br />So this is how you can construct a new feature with this text as its label:<br /><br />mapViewer.addPointFeature(centreX, centreY, 8265, "C.RED", textLabel, "MY_TEXT_STYLE",<br /> null, null, true);<br /><br />where MY_TEXT_STYLE should be a TEXT type style with "Honor newline" enabled.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-20490804750419241932009-07-06T10:27:00.003-04:002009-07-06T10:47:00.950-04:00MapViewer 11g R1 production kit releasedWe are excited to announce that as part of Oracle's Fusion Middleware 11g R1 release, MapViewer 11g R1 is now available for download! Please navigate to OTN MapViewer home page here: http://www.oracle.com/technology/products/mapviewer/index.html. The 11g R1 software can be found under the Software link on the right side of the page.<br /><br />Note that this release includes all the features and bug fixes of MapViewer patch 10.1.3.3 for WebLogic server, and we strongly encourage users to upgrade to the 11g R1 release to take advantage of the many new enhancements and a more stable Oracle Maps JavaScript API.<br /><br />It supports not only WebLogic server (and Oracle AS/OC4J 10.1.3.x), but also Tomcat 6.x and JBoss 4.x. The full certification matrix can be found here:<br />http://www.oracle.com/technology/products/mapviewer/htdocs/j2ee_server_support.html<br /><br />For the complete list of all the new and enchanced features of MapViewer 11g R1, please check out the New and Changed section of the MapViewer User's Guide, also downloadable from the OTN MapViewer home.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-39659399740509206432009-06-19T16:02:00.005-04:002009-06-19T16:51:41.674-04:00Running MapViewer on a WebLogic server clusterThis post describes how to deploy and run MapViewer version 11g R1 on a basic WebLogic cluster.<br /><br />For information and instructions on how to setup a simple WebLogic cluster, please check out this excellent <a href="http://andrejusb.blogspot.com/2009/04/weblogic-load-balancing-for-oracle-adf.html">blog post</a>. If you followed his instructions, you will have a WebLogic domain that contains a cluster of 3 managed servers. Lets call this the main domain. You will also create a second domain that contains a load balancing servlet (HttpClusterServlet) deployed as its only web application. Lets call this the proxy domain. The main domain's managed servers will be listening on ports 7003,7004 and 7005, while the proxy domain will be listening on 7001. You will deploy MapViewer to the main domain (specifically, to its cluster which is composed of the 3 managed servers), but access MapViewer via port 7001 such as http://localhost:7001/mapviewer. Each web session accessing MapViewer will be redirected to one of the 3 managed server's in a round-robin fashion.<br /><br /><span style="font-weight: bold;">Load balancing servlet's web.xml</span><br />While following Andrejus' instructions, when it's about time to deploy the load balancing servlet to the proxy domain, you will need to create a web.xml file for the servlet. You can use the sample web.xml, however for MapViewer to function completely, I have attached my own web.xml below. The main difference is that in my example I added url patterns for .jspx, .png, .gif and .jpeg so these files also get redirected to the managed servers from the proxy servlet.<br /><br /><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd";><br /><br /><web-app><br /><br /><servlet><br /><servlet-name>HttpClusterServlet</servlet-name><br /><servlet-class><br /> weblogic.servlet.proxy.HttpClusterServlet<br /></servlet-class><br /><br /><init-param><br /><param-name>WebLogicCluster</param-name><br /><param-value><br /> localhost:7003|localhost:7004|localhost:7005<br /></param-value><br /></init-param><br /><br /></servlet><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>/mapviewer</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.jsp</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.htm</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.html</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.js</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.png</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.jspx</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.gif</url-pattern><br /></servlet-mapping><br /><br /><servlet-mapping><br /><servlet-name>HttpClusterServlet</servlet-name><br /><url-pattern>*.jpeg</url-pattern><br /></servlet-mapping><br /><br /></web-app><br /><br /><br /><span style="font-weight: bold;">Deploy MapViewer</span><br />Deploying MapViewer to a cluster is actually no different from deploying it to a regular WebLogic server. Basically, follow these simple steps (for more details, please check out the MapViewer User's Guide which has a step-by-step guide):<br /><br /><ol><li>Create a WebLogic JDBC data source for your spatial database schema. Deploy (install) this data source to the cluster! This container data source will be the basis of the MapViewer data source to be created in step 3.<br /></li><li>Unpack mapviewer.ear and setup the required directory tree structure (again details can be found in MapViewer's User's Guide). This will be the working directory tree for MapViewer! Every WLS clustered server will start its own MapViewer instance out of this directory. Each started MapViewer instance will then load the config file from the WEB-INF/conf folder, as well as saving all generated map images and tiles into this same directory tree. If your managed servers span different physical machines, then this folder needs to be on a shared network drive accessible by all the managed servers.<br /></li><li>Modify the MapViewer config file, located in the WEB-INF/conf/ folder, to set a proper logging level. Most importantly, you need to create a MapViewer data source based on the container data source you created in step 1. A simple example of such a data source looks like this:<br /><map_data_source name="mvdemo"<br /> container_ds="jdbc/mvdemo"<br /> number_of_mappers="7"<br /> allow_jdbc_theme_based_foi="true"<br /> /><br />Another thing you must modify in the config file, is the <save_images_at> element. Make sure the url attribute is set to a URL that points to the proxy domain, for instance "http://localhost:7001/mapviewer/images". And change the path attribute to "../../images".<br /></li><li>Go to the console web page of the main domain, and deploy MapViewer from the exploded directory tree. Note that when presented with the "Soure accessibility" page during deployment, make sure you select the last option ("I will make the deployment accessible from the following location")! This is extremely important, as it ensures the MapViewer files are shared by all managed servers, and generated tiles/maps are shared also.</li><li>After deployment is done, simply access MapViewer from your browser http://localhost:7001/mapviewer. Everything should work just fine as if you are accessing a normal MapViewer server.<br /></li><li>Verify that there are 3 MapViewer instances are running. Go to the exploded MapViewer folder, and change into the directory mapviewer.ear/web.war/WEB-INF/conf/. There you should see a file mv_proc.id. Open it in any text editor, and you should see a number 3. This means MapViewer has acknowleged there are 3 separate instances running.<br /></li></ol><br />You now have a MapViewer deployed and running on a cluster of managed WebLogic servers. Each MapViewer instance will be accessing the same database schema using the same cluster-wide container data source for optimal usage of the JDBC connections. MapViewer will intelligently and automatically avoid file name conflicts when generating and saving map images, FOI images as well map tiles. This is critical in a clustered environment since all MapViewer instances share a single physical working directory tree (the exploded MapViewer folder).Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-85968887100888980462009-05-29T10:25:00.004-04:002009-05-29T10:56:21.949-04:00Using OpenStreetMap tiles with Oracle FMW MapViewer<span style="font-family:trebuchet ms;">The recently uploaded tutorial on using DigitalGlobe's online imagery delivery platform with MapViewer<br />(http://www.oracle.com/technology/sample_code/products/mapviewer/index.html) discuss the MVCustomMapTileLayer interafce for accessing 3rd party tile providers. This post consists of sample code showing how it can be used with OSM tiles from {tiles|tah}.openstreetmap.org.<br /><br />The sample html code is listed below.<br /><br /><html><br /><head><br /><META http-equiv="Content-Type" content="text/html" charset=UTF-8"><br /><TITLE>OpenStreetMap as external tile layer</TITLE><br /><!--<br /><link rel="stylesheet" type="text/css" href="/mapviewer/fsmc/tutorial/t.css" /><br />--><br /><link rel="stylesheet" type="text/css" href="http://sdolnx2.us.oracle.com:7777/mapviewer/fsmc/tutorial/t.css" /><br /><br /><!-- Change to your mapviewer instance e.g. localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js<br /><script language="Javascript" src="http://localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js"></script><br />--><br /><br /><script language="Javascript" src="http://sdolnx2.us.oracle.com:7777/mapviewer/fsmc/jslib/oraclemaps.js"></script><br /><br /><script language=javascript><br /><br />// set up a map tile configuration so MapViewer knows the tiling scheme, i.e.<br />// the number of zoom levels (20), tile size (256x256)<br />// the tile width & height in real world coordinates at each zoom level<br />// the coordinate system (Spherical Mercator EPSG:3785), and<br />// tile image file format (PNG)<br /> var mapConfig=<br /> {<br /> "mapTileLayer":"OSM_MERCATOR",<br /> "format":"PNG",<br /> "coordSys":<br /> {<br /> "srid":3785,<br /> "type":"PROJECTED",<br /> "distConvFactor":1.0,<br /> "minX":-2.0037508E7,"minY":-2.0037508E7,<br /> "maxX":2.0037508E7,"maxY":2.0037508E7<br /> },<br /> "zoomLevels":<br /> [<br /> {"zoomLevel":0,"name":"","tileWidth":4.00750166855785E7,"tileHeight":4.00750166855785E7,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":1,"name":"","tileWidth":2.0037508E7,"tileHeight":2.0037508E7,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":2,"name":"","tileWidth":1.0018754E7,"tileHeight":1.0018754E7,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":3,"name":"","tileWidth":5009377.0,"tileHeight":5009377.0,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":4,"name":"","tileWidth":2504688.5,"tileHeight":2504688.5,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":5,"name":"","tileWidth":1252344.25,"tileHeight":1252344.25,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":6,"name":"","tileWidth":626172.125,"tileHeight":626172.125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":7,"name":"","tileWidth":313086.0625,"tileHeight":313086.0625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":8,"name":"","tileWidth":156543.03125,"tileHeight":156543.03125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":9,"name":"","tileWidth":78271.515625,"tileHeight":78271.515625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":10,"name":"","tileWidth":39135.7578125,"tileHeight":39135.7578125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":11,"name":"","tileWidth":19567.87890625,"tileHeight":19567.87890625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":12,"name":"","tileWidth":9783.939453125,"tileHeight":9783.939453125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":13,"name":"","tileWidth":4891.9697265625,"tileHeight":4891.9697265625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":14,"name":"","tileWidth":2445.98486328125,"tileHeight":2445.98486328125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":15,"name":"","tileWidth":1222.992431640625,"tileHeight":1222.992431640625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":16,"name":"","tileWidth":611.4962158203125,"tileHeight":611.4962158203125,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":17,"name":"","tileWidth":305.74810791015625,"tileHeight":305.74810791015625,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":18,"name":"","tileWidth":152.87405395507812,"tileHeight":152.87405395507812,"tileImageWidth":256,"tileImageHeight":256},<br /> {"zoomLevel":19,"name":"","tileWidth":76.43702697753906,"tileHeight":76.43702697753906,"tileImageWidth":256,"tileImageHeight":256}<br /> ]<br /> };<br /> <br />// create a custom map tile layer based on the above tile configuration<br />// the second argument is a function that implements the getTileURL<br />// interface for this particular map tile service<br /> var osmBasemap = new MVCustomMapTileLayer(mapConfig, getOSMMapTileURL);<br /><br /><!-- Change to your mapviewer instance e.g. localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js<br /> var baseURL = "http://localhost:8888/mapviewer" ;<br /><br />--><br /> var baseURL = "http://sdolnx2.us.oracle.com:7777/mapviewer" ;<br /> var mapview;<br /> var oraTheme = null ;<br /> var oraTileLayer = null;<br /><br /> function showMap()<br /> { <br /> mapview = new MVMapView(document.getElementById("map"), baseURL);<br /> mapview.addMapTileLayer(osmBasemap);<br /> // near london -36793, 6679715 in SRID 3785<br /> var mpoint = MVSdoGeometry.createPoint(-36793.89, 6679715.42, 3785); // near london 0.1,51.5,8307<br /> <br /> mapview.setCenter(mpoint);<br /> mapview.setZoomLevel(10);<br /> <br /> mapview.addNavigationPanel() ; <br /> mapview.display();<br /> }<br /><br /> function showMapTileLayer(layerName)<br /> {<br /> mapview.removeMapTileLayer(osmBasemap) ;<br /> eval("mapview.addMapTileLayer("+layerName+"Basemap)") ;<br /> }<br /><br /><br /><br /> function getOSMMapTileURL(tx, ty, tw, th, level)<br /> {<br /> var x = (tx-mapConfig.coordSys.minX)/mapConfig.zoomLevels[level].tileWidth ;<br /> // Mapviewer's tile The tile numbering scheme, or mesh codes, for Oracle Maps’<br /> // (see Section 8.2 of the MapViewer User Guide for more details) tiles is similar<br /> // to that for Google Maps. There only difference is that the Y origin is<br /> // at the lower left rather than the upper left, as is the case for Google tiles<br /> var y = (mapConfig.coordSys.maxY-ty)/mapConfig.zoomLevels[level].tileHeight-1 ;<br /> // use mapnik rendered tiles<br /> //return "http://tile.openstreetmap.org/"+(level)+"/"+x+"/"+y+".png";<br /> // use osmarender instead<br /> return "http://tah.openstreetmap.org/Tiles/tile/"+(level)+"/"+x+"/"+y+".png";<br /> }<br /> <br /> </script><br /></head><br /><br /><body onload="javascript:showMap()"><br /><h3>Oracle Maps example - Custom map tile layer</h3><br />This sample shows how the Oracle Maps GetMapTileURL interface could be used to display OSM map tiles.<br />It implements code samples and technical details described on OSM sample code pages.<br />This code is purely a sample explaining how to use the GetMapTileURL interface.<br><br /><div id="map" style="width:800px;height:600px"></div><br /></body><br /></html><br /></span>Jayanthttp://www.blogger.com/profile/06118686005431618795noreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-16313722389655633172009-05-01T14:20:00.009-04:002009-05-01T14:52:00.837-04:00Storing your redline geometries in a databaseMapViewer's JavaScript API provides a simple Red-line tool that you can use to let user draw simple shapes on the map. The tool can also return the coordinates of the shape, but there is no built-in mechanism to persistently store these shapes. <br /><br />In this article I will show you how to easily store such hand drawings in a database table, then display them on the map at a later time just as easily.<br /><br />The mains steps are:<br /><br />1. Create a database table with a SDO_GEOMETRY column (to store the geometries). Also create spatial index on it so we can query and display the table contents on our map later on.<br /><br />2. Create a very simple JSP page that will handle the task of storing a single geometry. It will take an geometry in a simple string format, then store it in the table using JDBC.<br /><br />3. Create a simple HTML-based Oracle Maps demo page, where user can create a shape on the map using a Redline tool. After getting hold of the Redline geometry, the page will issue an AJAX request to the JSP page, passing various aspects of the geometry (such as its type, SRID, and coordinates) as URL parameters.<br /><br />4. Display the table as a dynamic theme in the same HTML page.<br /><br />For more details, please download the zip <a href="http://www.ljqian.com/oraclemaps/store.zip">file</a> that includes the following 3 files:<br /><br /><span style="font-weight:bold;">readme.txt</span>: Instructions for running this demo.<br /><span style="font-weight:bold;">store.jsp</span>: The JSP page that handles geometry storage.<br /><span style="font-weight:bold;">store.html</span>: The main demo page that lets you draw things and display stored geometries.<br /><br />The complete instructions are in the readme.txt file.<br /><br />If you have the built-in Oracle Maps tutorials running, this demo should be very easy to set up and run. To run the dmeo, simply open the store.html page in your browser. Post your comments below if you run into any issues. The following is a screenshot of the demo:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vMku6FYL_58/SftDUm3jFwI/AAAAAAAAAGI/eoGM7mJuXU4/s1600-h/redline-store.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 195px;" src="http://3.bp.blogspot.com/_vMku6FYL_58/SftDUm3jFwI/AAAAAAAAAGI/eoGM7mJuXU4/s320/redline-store.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5330928605233092354" /></a><br /><br /><br />Finally, note that you can easily expand the demo to store more fields besides the geometry itself. It is also trivial to display these fields as attributes in the info-tip window when user clicks on any geometry displayed on the map.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6774903665752106951.post-90969970846065196882009-03-26T15:03:00.008-04:002009-03-26T15:23:25.724-04:00Rotating map symbols using oriented pointsOracle Spatial supports the notion of oriented points, which are sdo_geometry points that contain additional coordinates of the end point for the orientation vector from the point itself, with values between -1 and 1. For instance, you can create an oriented point using the following SQL statement:<br /><br />INSERT INTO cola_markets VALUES(<br /> 91,<br /> 'oriented_point',<br /> <span style="font-weight: bold;">SDO_GEOMETRY(<br /> 2001,<br /> NULL,<br /> NULL,<br /> SDO_ELEM_INFO_ARRAY(1,1,1, 3,1,0),<br /> SDO_ORDINATE_ARRAY(12,14, 0.3,0.2))</span>);<br /><br />The 12,14 identifies the physical coordinates of the point; and the 0.3,0.2 identifies the x and y coordinates (assuming 12,14 as the origin) of the end point of the orientation vector. The resulting orientation vector slopes upward at about a 34-degree angle, as illustrated in this figure:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vMku6FYL_58/ScvS0wM9JoI/AAAAAAAAAF4/NePuJYzFyvs/s1600-h/oriented_pt.gif"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 304px; height: 303px;" src="http://2.bp.blogspot.com/_vMku6FYL_58/ScvS0wM9JoI/AAAAAAAAAF4/NePuJYzFyvs/s320/oriented_pt.gif" alt="" id="BLOGGER_PHOTO_ID_5317575588775274114" border="0" /></a><br /><br />(The above description and figure are copied from the Oracle Spatial User's Guide).<br /><br />MapViewer has built-in support for such oriented points. What this means, is that if you apply a MARKER or TEXT style to such points (via a theme defined on the points table for instance), the MARKER (map symbol) or text itself will be oriented on the map according to the angle of its underlying data point, for every displayed data point. <br /><br />To better illustrate this support, I have created a simple Oracle Maps demo that displays the included <span style="font-weight: bold;">oriented_points</span> table in your MVDEMO sample data set, using a pin symbol.<br /><br /><pre><br /><html><br /><HEAD><br /> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"><br /> <META NAME="GENERATOR" CONTENT="JDBC Demo"><br /><link rel="stylesheet" type="text/css" href="../t.css" /><br /><br /><script language="Javascript" src="/mapviewer/fsmc/jslib/oraclemaps.js"></script><br /><SCRIPT TYPE="text/javascript"><br /> var mapview;<br /> var orientedtheme;<br /> var baseQuery;<br /> var baseURL = "http://"+document.location.host+"/mapviewer";<br /> var mapCenterLon = -122.49;<br /> var mapCenterLat = 37.5106;<br /> var mapZoom = 3; <br /> var mpoint = MVSdoGeometry.createPoint(mapCenterLon,mapCenterLat,8307); <br /> function on_load_mapview() <br /> {<br /> mapview = new MVMapView(document.getElementById("map"), baseURL);<br /> var basemap = new MVMapTileLayer("mvdemo.demo_map");<br /> mapview.addMapTileLayer(basemap); <br /> mapview.setCenter(mpoint); <br /> mapview.setZoomLevel(mapZoom); <br /> <br /> orientedtheme= createOrientedTheme();<br /> <br /> mapview.addThemeBasedFOI(orientedtheme);<br /> <br /> var nav = new MVNavigationPanel() ;<br /> var navPan = new MVMapDecoration(nav,0,0,null,null,4,4) ;<br /> mapview.addMapDecoration(navPan) ;<br /><br /> mapview.display();<br /> }<br /> <br /> var pinMarker = "M.CYAN PIN" ;<br /> <br /> function createOrientedTheme()<br /> {<br /> baseQuery= "select shape from oriented_points";<br /> var theme = "<themes><theme name='a_dynamic_theme' >" +<br /> "<jdbc_query asis='true' spatial_column='shape' jdbc_srid='8307' " +<br /> "render_style='"+pinMarker+"' datasource='mvdemo'>" + baseQuery +<br /> "</jdbc_query></theme></themes>" ; <br /> var theme = new MVThemeBasedFOI('oriented-theme',theme); <br /> theme.setBringToTopOnMouseOver(true);<br /> return theme;<br /> }<br /> <br /></SCRIPT><br /></HEAD><br /><br /><BODY onload= javascript:on_load_mapview()><br /><h3>Displaying oriented points</h3><br /><div id="map" style=" width: 90%; height: 100%;"><br /><br /></BODY><br /></html><br /><br /></pre><br /><br />If you save the above code as an HTML file in your MapViewer web directory, then open it from a browser, you will see four pin symbols, rotated according to the angles of the four oriented points from the table.<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vMku6FYL_58/ScvU1q6G6HI/AAAAAAAAAGA/L-VllQvgjh0/s1600-h/oriented-pts.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 224px;" src="http://2.bp.blogspot.com/_vMku6FYL_58/ScvU1q6G6HI/AAAAAAAAAGA/L-VllQvgjh0/s320/oriented-pts.png" alt="" id="BLOGGER_PHOTO_ID_5317577803557169266" border="0" /></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6774903665752106951.post-28926264435537163532009-03-16T16:16:00.004-04:002009-03-16T16:27:51.042-04:00Creating a separate Admin account for MapViewer (part 2: WLS)In an earlier blog <a href="http://oraclemaps.blogspot.com/2009/01/creating-separate-mapviewer-admin.html">post</a> I described how to create a separate admin user for the MapViewer admin account in an Oracle Application Server 10.1.3.* installation. This post follows up with instructions for WebLogic Server (version 9 and later).<br /><br />To set up an admin user account for MapViewer in WLS, you first create a new user in WebLogic, then map this user to the MapViewer admin role in MapViewer's deployment descriptor file (weblogic.xml).<br /><br />So first lets create a new WLS user. This is done using the WebLogic Admin Console. <br /><br /><span style="font-weight:bold;">Creating a user:</span><br /><br /> 1. In the left pane select Security Realms.<br /> 2. On the Summary of Security Realms page select the name of the realm (for example, myrealm) that your MapViewer-deployed domain uses.<br /> 3. On the Settings for Realm Name page select Users and Groups > Users.<br /><br /> The User table displays the names of all users defined in the Authentication provider.<br /> 4. Click New.<br /> 5. In the Name field of the Create New User page enter the name of the user.<br /> User names are case sensitive and must be unique. <br /> 6. (Optional) In the Description field, enter a description. The description might be the user's full name.<br /> 7. In the Provider drop-down list, select the Authentication provider for the user.<br /><br /> If multiple WebLogic Authentication providers are configured in the security realm, they will appear in the list. Select which WebLogic Authentication provider’s database should store information for the new user.<br /> 8. In the Password field, enter a password for the user.<br /><br /> The minimum password length for a user defined in the WebLogic Authentication provider is 8 characters. Do not use the username/password combination weblogic/weblogic in production.<br /> 9. Re-enter the password for the user in the Confirm Password field.<br /> 10. Click OK to save your changes.<br /><br /> The user name appears in the User table<br /><br /><span style="font-weight:bold;">Assigning the new user to the MapViewer built-in admin role:</span><br /> <br />1. go to the exploded Mapviwer directory, find weblogic.xml under $MAPVIEWR_HOME/mapviewer.ear/web.war/WEB-INF/<br />2. open weblogic.xml in a text editor. You will see something like following:<br /><br /><?xml version = '1.0' encoding = 'US-ASCII'?><br /><br /><weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"><br /><br /><br /><security-role-assignment><br /> <br /><role-name>map_admin_role</role-name><br /> <br /><principal-name>weblogic</principal-name><br /><br /></security-role-assignment><br /><br /><br /><security-role-assignment><br /> <br /><role-name>secure_maps_role</role-name><br /> <br /><principal-name>weblogic</principal-name><br /><br /></security-role-assignment><br /><br /><br /></weblogic-web-app><br /><br />Replace the strings "weblogic" with the new user name. In my case I used "maplogic" as the new user name:<br /><br /><br /><?xml version = '1.0' encoding = 'US-ASCII'?><br /><br /><br /><weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90"><br /><br /><br /><security-role-assignment><br /> <br /><role-name>map_admin_role</role-name><br /> <br /><principal-name><span style="font-weight:bold;">maplogic</span></principal-name><br /><br /></security-role-assignment><br /><br /><br /><security-role-assignment><br /> <br /><role-name>secure_maps_role</role-name><br /> <br /><principal-name><span style="font-weight:bold;">maplogic</span></principal-name><br /><br /></security-role-assignment><br /><br /><br /></weblogic-web-app><br /><br /><br />Save this file. Then restart the domain. Now you will be able to use the new user and password to log into MapViewer's admin page.Unknownnoreply@blogger.com0