ArcGIS development using the Java API


In this topic


Import directives

Java import statements allow fully qualified class names to be shortened to their simple names. The following code example uses simple class names and assumes the corresponding import statements are in effect:
[Java]
import com.esri.arcgis.system.beans.reader.*;
import com.esri.arcgis.system.datasourcesfile.*;
import com.esri.arcgis.system.*;
import com.esri.arcgis.system.geodatabase.*;
import com.esri.arcgis.system.geometry.*;

Multiplatform development

  • Data and paths—For multiplatform compatibility, the data and path names must be in all lowercase letters (using uppercase letters produces problems). In addition, the path type must be accessible on Solaris or Linux machines. The standard types of paths—absolute, relative, and Universal (or Uniform) Naming Convention (UNC)—are supported in ArcGIS. However, absolute paths, when created in a Windows application, are Windows-centric and not accessible on other platforms. It is recommended that relative paths be used for cross-platform development.
  • Runtime mode—On Solaris and Linux, set JAVA_HOME environment variable and source the init_java.sh script as explained in the Post Installation topic.
  • Personal geodatabases—Personal geodatabases are not supported on Solaris or Linux. Personal geodatabases must be converted to a multiuser geodatabase (ArcSDE) or to a supported file based format, such as shapefiles, coverages, or raster data before it can be used in a Solaris or Linux implementation.
  • Post crash cleanup—If an application running Solaris or Linux does not exit clean, it is possible that processes remain. The mwcleanup utility must be used to clean up these processes. Typing mwcleanup at the command prompt kills all running ArcGIS applications and cleans up all X properties.

Interfaces

Native ArcObjects use an interface based programming model. The concept of an interface is fundamental to ArcObjects and emphasizes the following points:
ArcObjects interfaces are abstract, which means there is no implementation associated with an interface. Objects use type inheritance; the code associated with an interface comes from the class implementation.
This model shares some features of the Java interface model. In Java, an interface is a specification of methods that an object declares it implements. A Java interface does not include instance variables or implementation code.
The ArcGIS application programming interface (API) for Java has two objects for every ArcObjects interface: a corresponding interface and an interface proxy class. The interface is named in the ArcObjects style, prefixed with the letter I. The interface proxy class appends the term proxy to the name. For example :
COM:
interface IArea : IUnknown 
Java:
public interface IArea{} 
public class IAreaProxy implements IArea{}
The proxy classes are used internally by the ArcGIS API for Java to provide implementation to respective interfaces. Do not use the default constructor of these classes as it holds no implementation. ArcObjects requires developers to go through an interface to access objects. The Java language does not use this model; subsequently, the ArcGIS API for Java has two ways of accessing objects—by interface or by class. See the following code example: [Java]
/* Use the class implementing IPoint. */
IPoint iPoint = new com.esri.arcgis.geometry.Point();
/* Access objects through class. */
Point cPoint = new Point();
You cannot access objects through the default interface proxy class. See the following code example:
[Java]
IPointProxy proxyPoint = new IPointProxy(); // Incorrect usage.
ArcObjects interfaces are immutable and subsequently never versioned. An interface is never changed once it is defined and published. When an interface requires additional methods, the API defines a new interface by the same name with a version number appended to it as shown below.
interface IGeometry : IUnknown —public interface IGeometry{}
interface IGeometry2 : IGeometry—public interface IGeometry2 extends IGeometry{}
interface IGeometry3 : IGeometry2—public interface IGeometry3 extends IGeometry2{}
interface IGeometry4 : IGeometry3— public interface IGeometry4 extends IGeometry3{}

Classes

In the ArcObjects model, classes provide the implementation of the defined interfaces. ArcObjects provides three types of classes: abstract classes, classes, and coclasses. These class types can be distinguished through the object model diagrams (OMDs) provided in the ArcGIS documentation for developers. It is important to be familiar with the OMDs before you begin to use the three class types.
In ArcObjects, an abstract class cannot be used to create new objects and are absent in the ArcGIS API for Java. These classes are specifications in ArcObjects for instances of subclasses through type inheritance. An abstract class enumerates the interfaces that are implemented by the implementing subclass, but does not provide an implementation to those interfaces. For each abstract class in ArcObjects there are subclasses that provide the implementation.
A class cannot be publicly created in ArcObjects; however, objects of this class type can be created as a property of another class or instantiated by objects from another class. In the ArcGIS API for Java, the default constructor normally used to create a class is undefined for ArcObjects classes. See the following code example:
[Java]
/* The constructor for FeatureClass() is unsupported.*/
FeatureClass fc = new FeatureClass(); //Incorrect usage.
The following code example shows this behavior while stepping through the process of opening a feature class:
[Java]
IWorkspaceFactory wf = new ShapefileWorkspaceFactory();
IFeatureWorkspace fw = new IFeatureWorkspaceProxy(wf.openFromFile("\path\to\data", 0)
    );
/* Create a feature class from FeatureWorkspace. */
IFeatureClass fc = fw.openFeatureClass("featureclass name");
In ArcObjects, a coclass is a publicly creatable class, which means you can create your own objects by declaring a new object. See the following code example:
[Java]
/* Create an envelope from the Envelope coclass. */
Envelope env = new Envelope();

Structures

Structures (structs) define a new data type made up of elements (members). Java does not have structures as complex data types. The Java language provides this functionality through classes; you can declare a class with the appropriate instance variables. For each structure in ArcObjects, there is a representative Java class with publicly declared instance variables matching the structure members. One such example is the _WKSPointZ class. See the following code example:
[Java]
public class _WKSPointZ{
    public double x;
    public double y;
    public double z;
}
You can work with these classes like any other class in Java. See the following code example:
[Java]
_WKSPointZ pt = new _WKSPointZ();
pt.x = 2.23;
pt.y =  - 23.14;
pt.z = 4.85;
System.out.println(pt.x + " " + pt.y + " " + pt.z);

Enumerations

Java 2 software development kit (SDK) prior to version 5 did not have enumeration (enum) types. To emulate enums in Java, a class or interface must be created that holds constants. For each enumeration in native ArcObjects, there is a Java interface with publicly declared static integers representing the enumeration value. See the following code example:
[Java]
public interface esri3DAxis{
    public static final int esriXAxis = 0;
    public static final int esriYAxis = 1;
    public static final int esriZAxis = 2;
}
You can now refer to the esriXAxis constant using the following code example:
[Java]
esri3DAxis.esriXAxis;

Methods that take out parameters

ArcObjects provides many methods that return more than one value. The ArcGIS API for Java sends single element arrays as parameters to these methods. Basically, you pass in single element arrays of the object that you want returned and ArcObjects fills in the first elements of those arrays with the return value.
Upon returning from the method call, the first element of the array contains the value that has been set during the method call. One such method, is the toMapPoint of IARMap interface. See the following code example:
[Java]
public void toMapPoint(int x, int y, double[] xCoord, double[] yCoord)throws
    IOException, AutomationException
The above method converts a point in device coordinates (typically pixels) to coordinates in map units. It converts the x and y screen coordinates supplied in pixels to x and y map coordinates. The returned map coordinates will be in MapUnits.

Parameters:
x - The x (in)
y - The y (in)
xCoord - The xCoord (in/out: use single element array)
yCoord - The yCoord (in/out: use single element array)
The parameters xCoord and yCoord are marked as in/out: use single element array. To use this method, the first two parameters are the x,y coordinates in pixel units. The next two parameters are used to get return values from the method call. You pass in single dimensional single element double arrays. See the following code example: [Java]
double[] dXcoord = {
    0.0
};
double[] dYcoord = {
    0.0
};
When the method call completes, you can query the values of dXcoord[0] and dYcoord[0]. These values will be modified by the method and will refer to the x,y coordinates in map units. A practical example of this method call is to update the status bar with the current map coordinates as the mouse moves over the control. See the following code example:
[Java]
public void updateStatusBar(IARControlEventsOnMouseMoveEvent params)throws
    IOException{
    /*Create single dimensional array of doubles.
     *The values of the first element of the arrays will be filled in
     *by the arMap.toMapPoint(...) method.
     */
    double[] dXcoord = {
        0.0
    };
    double[] dYcoord = {
        0.0
    };
    int screenX = params.esri_getX();
    int screenY = params.esri_getY();
    IARMap arMap = arControl.getARPageLayout().getFocusARMap();
    arMap.toMapPoint(screenX, screenY, dXcoord, dYcoord);
    /*Set the statusLabel.*/
    statusLabel.setText("Map x,y: " + dXcoord[0] + ", " + dYcoord[0]);
}
The ArcGIS API for Java will not allow developers to populate an array with a superclass type, even when it has been cast to a superclass type. See the following code example:
[Java]
Integer[] integers = {
    new Integer(0), new Integer(1), new Integer(2)
};
Object[] integersAsObjects = (Object[])integers;
integersAsObjects[0] = new Object();
The previous code example is not allowed and will cause an ArrayStoreException. Consider the following code example: [Java]
Polyline[] polyline = {
    new Polyline()
};
tin.interpolateShape(breakline, polyline, null);
Polyline firstPolyLine = polyline[0];
The preceding code example is not allowed and will cause the same ArrayStoreException as the previous example. In the following code example, review and analyze the interpolateShape() method of ISurface:
[Java]
public void interpolateShape(IGeometry pShape, IGeometry[] ppOutShape, Object
    pStepSize)throws IOException, AutomationException
Parameters:
pShape - A reference to a com.esri.arcgis.geometry.IGeometry (in)
ppOutShape - An reference to a com.esri.arcgis.geometry.IGeometry (out:    use single element array)
pStepSize - A Variant (in, optional, pass null if not required)
Throws:
IOException - If there are communications problems.
AutomationException - If the remote server throws an exception.
IGeometry is a superinterface to IPolyline, and the Polyline class implements both interfaces. In the first attempt, you tried to send a single element Polyline array into a method that requires an in/out IGeometry parameter. This causes an ArrayStoreException as ArcObjects is attempting to populate an IPolyline array with an IGeometry object, attempting to place a superclass type into a subclass array. The correct way to use this method is shown in the following code example:
[Java]
/*Set up the array and call the method.*/
IGeometry[] geoArray = {
    new Polyline()
};
tin.interpolateShape(breakline, geoArray, null);
/* Cast the first array element as a Polyline. This is
 * the equivalent of calling QueryInterface on IGeometry.
 */
IPolyline firstPolyLine = new IPolylineProxy(geoArray[0]);

Non-OLE automation compliant types

A few ArcObjects types are not Object Linking and Embedding (OLE) automation compliant. They contain methods that do not work in the ArcGIS API for Java. The API addresses each of these situation in one of the following ways:
[Java]
/* Not automation compatible, throws exception. */
IEnvelope env = new Envelope();
env.defineFromPoints(2, somePoints[0]);
/* Automation compatible. */
IEnvelopeGEN envGEN = new Envelope();
envGEN.defineFromPoints(somePoints);
  • A singleton utility class implements bridge interfaces. Since each utility class can handle methods from multiple noncompliant interfaces, there is no naming convention for the utility classes. The bridge interfaces handle the effort of converting between noncompliant and compliant methods. In these cases, the noncompliant methods are deprecated, with a link to the appropriate bridge method in the utility class. To call the bridge method, pass in the noncompliant object as the first argument. In the following code example, myPointCollection4 is an instance of IPointCollection4 and somePointStructures is an array of WKSPointZ objects with four objects.
[Java]
/* Not automation compatible. Throws exception. */
myPointCollection4.addWKSPointZs(4, somePointStructures[0]);

/* Automation compatible. */
GeometryEnvironment geomEnv = new GeometryEnvironment();
geomEnv.addWKSPointZs(myPointCollection4, somePointStructures);