Friday, September 18, 2009

Why am I getting "Request string is too long for Oracle Maps' non-AJAX remoting"?

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.

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.

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.

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.

To solve this problem, you have two options.

Option 1
---------
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.

In your application code, you need to call MVMapView.enableXMLHTTP(true) at the beginning of your showMap function.

function showMap()
{
MVMapView.enableXMLHTTP(true);
var baseURL = "http://hostB/mapviewer";
mapview = new MVMapView(mapDiv, baseURL) ;
...
}

Option 2
---------
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/mapviewer/* and forward them to http://hostB/mapviewer/*. If your HTTP server is Apache, then this can be done by adding the following two lines inside mod_proxy section in httpd.conf.

<IfModule mod_proxy.c>
ProxyRequests Off

<Directory proxy:*>
Order deny,allow
Deny from 127.0.0.1
Allow from all
</Directory>

ProxyPass /mapviewer/ http://hostB/mapviewer/
ProxyPassReverse /mapviewer/ http://hostB/mapviewer/

</IfModule>


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.

function showMap()
{
var baseURL = "http://"+document.location.host+"/mapviewer" ;
mapview = new MVMapView(mapDiv, baseURL) ;
tileLayer = new MVMapTileLayer("myds.my_map", "http://hostB/mapviewer/mcserver");
...
}