Opening the ArcIMS WMS Connector with Java

August 5th, 2008

In order to WMS enable a map service in ArcIMS an operator must use the WMS connector manager, a user interface that’s a set of JSP pages. Users must manually select a service and navigate the menus for a service to become available via the WMS connector. However, there is a way to do this in Java.

If you’re working with the Java connector you can enable an ArcIMS service dynamically using the following JSP/Java code. This is accomplished using an applications server proxy to send commands via http post to your ArcIMS connector that will generate and seed the directories with the needed WMS capabilities data.

Here is your basic JSP page. Use request.getParameter() or session.getAttribute() or jsp:forward tags to manage the specific parameters such as add/delete and service name.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″ %>
<%@ page import=”java.util.*, java.io.*, java.net.*, com.esri.wms.*, com.esri.wms.Esrimap” session=”true” %>

<%@ taglib uri=”http://jakarta.apache.org/taglibs/i18n-1.0” prefix=”i18n” %>

<i18n:bundle id=”resBundle” baseName=”Res” debug=”false” />
<%

    application.setAttribute(”resBundle”, resBundle);
   
      // Initialize the Esrimap class without a redirect
      String s = “”;

 try {
     URL u;
            u = new URL(”http://<your server name>:8080/wmsconnector/com.esri.wms.Esrimap?request=capabilities&charset=ISO-8859-1″);
     
     // Open the connection and prepare to POST
     URLConnection uc = u.openConnection();
     uc.setDoOutput(true);
     uc.setDoInput(true);
     uc.setAllowUserInteraction(false);

     DataOutputStream dstream = new DataOutputStream(uc.getOutputStream());
     
     // The POST line
     dstream.writeBytes(s);
     dstream.close();

     // Read Response
     InputStream in = uc.getInputStream();
     int x;
     while ( (x = in.read()) != -1) {
                System.out.write(x);
     }
     in.close();

     BufferedReader r = new BufferedReader(new InputStreamReader(in));
     StringBuffer buf = new StringBuffer();
     String line;
     while ((line = r.readLine())!=null) {
                buf.append(line);
     } 

 } catch (IOException e) {
     e.printStackTrace(); // should do real exception handling
 }

        boolean enabled;
        String dStatus;
       
        AdminCommand myAdm;
        AppServerProxy myProx = new AppServerProxy(”<your server name>”, 5300);
       
        myAdm = new AdminCommand(myProx, “<IMS Map Service name>”);
        enabled = AdminCommand.checkCapabilitiesPresentOnDisk(”<IMS Map Service name>”);
            if (!enabled)
                dStatus = myAdm.updateCapabilitiesOnDisk(request, response, “wms”);
      
       // Could also use deleteCapabilitiesOnDisk(request, response, “wms”);
       
%>

<HTML>
<HEAD>
<TITLE>HGL Dynamic WMS Startup</TITLE>
</HEAD>
<BODY>

 First, put the JSP you want to use into the WMSCONNECTOR context. (unless you copy classes to your own context)<BR>
 Second, initialize the class:<BR>
 u = new URL(”http://<your server name>:8080/wmsconnector/com.esri.wms.Esrimap?request=capabilities&charset=ISO-8859-1″); <BR>

<BR>The initial parameters needed…<BR>
Missing mandatory REQUEST parameter. Possibilities are
   {capabilities|GetCapabilities|map|GetMap|feature_info|GetFeatureInfo}
</BODY>
</HTML>

Referencing a custom map projection in ArcIMS as an EPSG code

June 17th, 2008

Several projects I’m involved with have a requirement to interface with map APIs such as Google and Yahoo. However, Google adopted a Spherical Mercator projection and morphed it to their own needs. This “custom” projection is not supported in some GIS software as a standard coordinate system. Rather, users must for example pass an entire coordinate system reference string when making an open source (WMS) map request. This can cause errors that prevent a getMap request from completing. For my new HGL user interface this is a huge problem because ArcIMS does not support the Google map projection as a native EPSG code. The following is a work-around (in Linux) process for defining a custom ArcIMS projection for use in an ArcIMS WMS connector. This solution does not require the WMS request to pass full projection parameters each time there is communication with the ArcIMS WMS servlet!

Pick a web accessible place for your projection file. Name it projcs and add the custom projection properties in it;

PROJCS,2002100,”NRCan_LCC_Canada”,PE_GCS_NAD_1983,PE_PRJ_LAMBERT_CONFORMAL_CONIC,PE_PAR_FALSE_EASTING,0.0,PE_PAR_FALSE_NORTHING,0.0,PE_PAR_CENTRAL_MERIDIAN,-95.0,PE_PAR_STANDARD_PARALLEL_1,49.0,PE_PAR_STANDARD_PARALLEL_2,77.0,PE_PAR_LATITUDE_OF_ORIGIN,49.0,PE_U_METER

Add a variable to your .bash_profile and set the path to your custom projection file location;

PEOBJEDITHOME=/home/ims92/arcgis
export PEOBJEDITHOME

In your aimssaimsserver.cfg add the PEOBJEDITHOME. Any CR/LF WILL break this!

<AIMSSERVER debug=”false”
logpath=”"
logtype=”log”
logformat=”"
logmaxsize=”"
logmaxlines=”"
logmaxfiles=”"
logsavefiles=”true”
logmsglevel=”2″ >
PEOBJEDITHOME=”/home/ims92/arcgis”
<LOGTYPES>
</LOGTYPES>

Now make your map AXL file and add the following elements to reference your projection;

<FEATURECOORDSYS id=2002100>
<FILTERCOORDSYS id=2002100>

Publish your AXL to an ArcIMS ImageServer service

Enable your map service as WMS - I use the web admin;

http://<your server name>:8080/wmsconnector

Using a GetCapabilities request, check the response and verify that code EPSG:2002100 is listed

You should be done.

Drupal Notes

April 23rd, 2008

Drupal Installation notes

DRUPAL_NOTES

what has been driving me insane is to figure out how to drive panels and views based on the user logged in.   my first success worked roughly as follows:

1)  enabled minimum of CCK, Views, Views RSS, JQuery Update, JQuery Interface, Panels 2

2)  use CCK to create specific content types that users will be allowed to create

3)  create a vocabulary in Taxonomy for top level channels of content, require selection of one for each CCK type

4)  log in as user A and create several items of each CCK type

5)  log in as user B and create some other items of each CCK type

6)  set up a View that allows those users access and then set two Filters

7)  first Filter:  Node: Author is Current User

8)  second Filter:  Taxonomy: Terms for channels  (then pick the Channel related to ONE of the CCK types)

9)  you may want to provide the View as a Block

10)  now when you go to the URL for the View you should see only the content for the selected CCK type & logged in User

11)  logout and try the same URL for the View after logging in as a different user, now you should see different content

12)  If this works, then you should be able to create a Panel page, upon which you can add the newly create View

13)  try the same test by looking at the URL for the Panel page logged in as different users

14)  if the Panel page is pulling content correctly based on User ID, then slug a MENU item in for the Panel Page

15)  now whenever a user logs in and clicks on the Menu Item for that Panel page, it will only view THEIR stuff!

MapQuest goes Fujax

March 10th, 2008

Just when you thought you had GoogleMaps and OpenLayers figured out, Mapquest decides to go FUJAX on us. Anyway, the prospects look pretty interesting since it is supposed to convert JavaScript to SWF (Flash Version 9 and higher plugins).

**LINK**

How to import a table with latitude longitude values and save as a shapefile in ArcMap

March 3rd, 2008

How to import a table with latitude longitude values and save as a shapefile in ArcMap (word doc)

 

1)      Make sure the field names in your table don’t contain any spaces or special characters such as:  \ ? < > / ‘ “

The data to be imported can be in .xls, .dbf, .csv, or text comma or tab delimited format.

 

2)      In ArcMap, click Tools > Add XY Data.

Click the Browse to Folder button in the “Choose a table from the map or browse for another table” window, browse to the input table, double click on it to choose it.  If it is an Excel spreadsheet, you’ll have to specify the workbook within the .xls file as well.

 

3)   In the X Field choose the LONGITUDE (or corresponding) field from your table.

In the Y Field choose the LATITUDE (or corresponding) field from your table.

Click the Edit button.

Select > Geographic Coordinate Systems

If you know the geographic coordinate system used when producing your data, choose it.  If not, select  World > WGS 1984.prj  This is the most common geographic system used for worldwide data.  The window should look like this:

 

Click OK.  If a “Table does not have Object-ID field” warning appears, Click OK.  The data will be added to the map as an event layer named <input table> Events. 

 

4)       Right click this layer in the table of contents, and choose Data > Export Data.  Specify the name and location on disk of the new shapefile to be created.  Make sure All Features  and Use the same coordinate system as this layer’s source are chosen.  Click OK, and Yes to add the layer to the map when prompted.  This is the new shapefile.  Remove the <input table> Events layer.

Spatio Temporal Network Model for Google Earth

February 28th, 2008

Well, with the launch of teKML I am now able to run some interesting queries on the CHGIS database and pipe the results into time enabled KML.

Spatio Temporal Network of the Sui Dynasty (circa 601 CE)

To accomplish this I wrote several PHP scripts. The first script takes the ID number for a particular Top Level Unit (for the test case I used the Sui Dynasty since it is so short, 581 CE to 618 CE), then finds its immediate children (the ADM1 units). For each ADM1 level child, the PHP script creates two pairs of coordinates (begin and end nodes) and writes them out to KML. The resulting KML will show the network of the SUI Dynasty from the central capital (at Chang’an) to the ADM1 capitals (in this case Jun), and represent them with 4 pixel wide blue lines.

The second script begins with the same Top Level ID (capital of the SUI), but this time goes down to a second level of the hierarchy. For each ADM1 level capital, it finds all the subordinate units, and sets up two pairs of coordinates to draw a 2 pixel wide red line between them. The sample image above is a snapshot of the ADM1 units as parents, showing the relationships to their subordinate ADM2 level units (in this case Xian) as a network of red lines.

After the PHP scripts output KML to a browser, the page is saved as KML file (with .kml extension instead of .php), and is run through teKML which parses the ISO 8601 year values into the format that KML needs. (see the documentation on teKML for details on the date conversions). The output from teKML are time enabled KML versions of the Top-to-ADM1 and the ADM1-to-ADM2 networks.

Sui Dynasty Space Time Network KML samples

The original PHP scripts, set up for use with CHGIS mySQL database, are also made available here:

Spatio Temporal Network script

(posted by Lex Berman) 

Export coordinates from Access for Add XY Event

February 26th, 2008

One of the common tasks we have when working with CHGIS is to edit a specific subset of historical places in a database (Access) and then export a query selection for mapping in ArcMap. One of the problems that comes up is that Access automatically truncates Number - Double data type values to two digits past the decimal. Of course, the values need to be Number data types, in order for ArcMap to read them as coordinate values using the ADD XY Event tool.

The solution to this is to open the Access Query in Design View, then switch to SQL VIEW. At that point you will see something like this:

SELECT TableName.name_py, TableName.name_ch, TableName.sys_id, TableName.x_coord, TableName.y_coord, TableName.src_nts
FROM TableName
WHERE (((TableName.name_py)=”Placename”));

To prevent the x_coord and y_coord values from truncating during the export to TXT file process, change the section [ TableName.x_coord, TableName.y_coord, ] to the following (minus the brackets, of course):

[ Trim(Str(TableName.x_coord)) AS x, Trim(Str(TableName.y_coord)) AS y, ]

This will take your x_coord value and export it as a field named x, and the y_coord value as a field named y, while at the same time preserving all the decimal values that were set in the original table’s Design View Decimal Places setting.

Note: during the export to TXT, hit the Advanced button and set the following:

Field delimiter = ,

Text qualifier = {none}

Language = English

Encoding = UTF-8 (or as needed)

The important part for us is Text qualifier = {none}, which will prevent the output Number Strings from being interpreted as text by ArcMap.

In the next step check “Include Field Names on First Row” then Finish.

Once you have exported to TXT file, go to ArcMap and use TOOLS | Add XY Data to select the TXT file. The X, Y fields should show up in the appropriate X Field and Y Field form. Hit OK and check the resulting attribute table of the TXT file Event. Your coordinates will not have been truncated, and your UTF-8 characters will not be garbled. (Though you may have to turn on your shell interpreter software, such as NanjiStar to view the characters).

(posted by Lex Berman)

Notes on Drupal

February 14th, 2008
  1. Installing Views - if you enable the Views module and your screen goes blank, you probably need to boost the setting for [memory_limit] in your php.ini file. Mine was set to the default of 8MB. I boosted it to 32MB (probably overkill) and restarted apache. Next time installing Views went through without a hitch. However, you’re probably wondering “but what about the blank screen? how do I get Drupal back??” Which leads me to the next item
  2. If you install or delete any Drupal module and your whole Drupal site vanishes, there is a way to fix it by going into MySQL and editing the [system] table. Login to your Drupal’s MySQL database as root, then use the following command [with your module name instead of “moduleName”]: update system set status=0 where name LIKE ‘moduleName%’; Now you can go back to the site building | modules section of Drupal and either enable or delete the module.

(posted by Lex Berman)

Serialize to XML - GeoRSS, School of Hard Knocks

February 1st, 2008

Well, I wrote some code in PHP (download here) that sends the results from a query to MySQL out to RDF XML. My great misfortune was that the contents of the table I was querying was a pot-pourri of catalog info in Japanese, Korean, Vietnamese, etc. What I didn’t know but soon found out, is that if you are pushing strings to XML you have to be really strict about escaping ugly characters. The main culprits, in my case turned out to be:

colons :

commas ,

apostrophes ‘

ampersands &

The colons and commas I ended up replacing completely with hyphens, while the others got replaced with appropriate escape strings [’ = ‘ and & = &].

My real misfortune is that, even after I meticulously cleaned out all the mess in the “romanized” parts of the data (including a whole bunch of Vietnamese special characters), there were still some lingering backwards commas, singles quotes, & other marks embedded in the UTF vernacular strings that had to pulled out, one by one, like needles from a prickly pear cactus out of your tender parts. OUCH!

The trick to finding these, was to run sequential chunks of the XML file through an online XML DOM validator, which throws an error at the exact line and colum, thank goodness! When the whole ugly process was finished, I could then easily serialize the query results from MySQL to the XML file, then point to it with OpenLayers GeoRSS call. You can see the resulting test map here.

**ADDED LATER**

By the way, I found out a few things when validating RSS that you might want to know. Even if you set your [ charset=”UTF-8″] properly, the instance of Apache serving it might not be set to the default (which is UTF-8). In that case, add a line to your apache httpd.conf file and restart:

AddCharset UTF-8 .xml

Similarly, the validator might not like it if Apache hasn’t been told to push RSS, so add the following and restart just for good measure:

#add application for RSS feed
AddType application/rss+xml .xml

After doing this my sample RSS feed that was autogenerated by the mysql_to_geoRSS PHP script validates fine!

(posted by Lex Berman)

OpenLayers Proxy setting

January 30th, 2008

The instructions for setting up the Proxy host in OpenLayers are missing some important info. The following is what worked for me.

The line used in OpenLayers call to Proxy was:

OpenLayers.ProxyHost=”/cgi-bin/proxy.cgi/?url=”;

However, the actual proxy.cgi script provided by OpenLayers is written in Python. Therefore you need to make sure that your Apache httpd.conf file knows that a call to .cgi needs python.

Make sure that the AddHandler section of your httpd.conf file contains the line:

AddHandler python-cgi-script .cgi

then restart Apache. Everything should work!

(posted by Lex Berman)