ArcGIS SDK  

Development Environments

Walkthrough 1 Java: Getting started with ArcGIS Engine

This article is targeted towards GIS developers who are new to ArcGIS Engine and the ArcObjects components that comprise the ArcGIS platform. The material is divided into a number of logical sup-topics.

This article is not intended to serve as an introduction to ArcObjects. It also deals specifically with ArcGIS Engine and does not include a discussion of programming with ArcObjects components for ArcGIS Server.

The separate article, Getting started with ArcGIS Server, highlights server usage of the ArcObjects API.

The code examples presented in this tutorial are available as a package bundled in a jar file, HelloAOsrc_jar.zip, that can be used from the command line or imported into any IDE.

The following outline provides quick links to the topics discussed in this tutorial:

 

An example program—Hello, Sphere!

Example 1 below shows an ArcObjects program that displays a sphere. The output of running this program is displayed as Figure 1 in the next section, 'Compiling and running the program'.

[Java]
Example 1 - HelloSphere.java: A program to display a sphere

 1 import java.awt.BorderLayout;
 2 import java.awt.event.WindowAdapter;
 3 import java.awt.event.WindowEvent;
 4 import javax.swing.JFrame;
 5 import java.io.IOException;
 6 import com.esri.arcgis.beans.globe.GlobeBean;
 7 import com.esri.arcgis.system.AoInitialize;
 8 import com.esri.arcgis.system.EngineInitializer;
 9 import com.esri.arcgis.system.esriLicenseProductCode;
10 /**
11  * Display a sphere.
12  */
13 public class HelloSphere {
14     public static void main(String args[]) throws IOException {
15         EngineInitializer.initializeVisualBeans();
16         new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
17         JFrame jFrame = new JFrame("Hello, Sphere!");
18         jFrame.setSize(300, 300);
19         jFrame.getContentPane().add(new GlobeBean(), BorderLayout.CENTER);
20         jFrame.addWindowListener(new WindowAdapter() {
21             public void windowClosing(WindowEvent e) {
22                 try {
23                     new AoInitialize().shutdown();
24                     System.exit(0);
25                 }
26                 catch (IOException ex) {
27                     System.out.println(ex.getMessage());
28                     System.exit(1);
29                 }
30             }
31         });
32         jFrame.setVisible(true);
33     }
34 }

The program listing above and all example code provided in this article include line numbers for discussion purposes; however, the ZIP file that accompanies this article includes the code without the line numbers.

 

Compiling and running Hello, Sphere!

Before looking at how the program works, let's talk about how to compile and run it.

A Java Runtime Environment (JRE) is included with the ArcGIS software developer kit (SDK) for Java, but a Java compiler is not. With ArcGIS 9.1, the included JRE is version 1.4 from Sun; as such, ensure that whatever compiler you use is compatible with that version of JRE.

In addition, the compiler needs to know where your class files are. The ArcGIS Engine Runtime contains all the ArcObjects classes packaged into a set of Java Archive (JAR) files. For convenience, two supersets of those JAR files are provided that contain all the other JARs. The first of the superset JARs is specifically for applications that use the ArcGIS visual JavaBeans and is named arcgis_visualbeans.jar. The second is intended for applications that don't use the visual beans and is named arcobjects.jar. On Windows platforms, both of these JARs are typically located in <drive:>\Program Files\ArcGIS\java\opt and on non-Windows machines they are similarly found in <install location>/arcgis/java/opt. In addition to these two JAR files, another set of classes is needed for communication purposes; these are packaged into the jintegra.jar, which is located /java directory, up one level from the core JAR files. Each of these three JAR files should be on your CLASSPATH or known by your IDE.

Finally, to actually run this program you need some extra information.

More details about setting up your environment are available in the document Java platform configuration for ArcGIS.

Now you're ready to run the program.

Figure 1 - HelloSphere output

 

Analyzing Hello, Sphere!

HelloSphere is a Swing application. Therefore, the first 4 lines of code import AWT and Swing types. Lines 6 through 9 are imports for the ArcObjects types used in this program.

All ArcObjects programs should do at least two things—initialize the ArcObjects system and then shut it down. Initialization itself is a multipart process depending on the particular application:

  1. The first step is to set up communication between the native ArcObjects components and their corresponding Java classes, which the EngineInitializer class performs.
  2. Next, permissions need to be established through licensing and checking out extensions, which the AoInitialize class handles.

The shutdown process releases resources and tells ArcObjects that its services are no longer needed.

In the Hello, Sphere! example, line 15 establishes communication settings by calling the static method initializeVisualBeans() which also tells ArcObjects that you will be doing graphical operations involving the ArcGIS visual JavaBeans. If no visual beans were to be used, this program could have instead called the static method initializeEngine(). You don't need to call initializeEngine() if you call initializeVisualBeans(). In fact, the best practice is to call one or the other, but not both.

Refer to the document ArcGIS development visual JavaBeans for more on initializing the beans.

Line 16 tells ArcObjects that this program will use an ArcGIS Engine license. If this application needed any additional permission to run, it would have additionally checked out license extensions here. ArcGIS Engine-based applications can run against the ArcGIS Engine Runtime license or, if available and coded appropriately, an ArcGIS Desktop license such as ArcView, ArcEditor, or ArcInfo; a development and test version of the ArcGIS Engine Runtime license is available with the ArcGIS Engine SDK for Java.

See Chapter 5, 'Licensing and deployment', of the ArcGIS Engine Developer Guide for a detailed discussion of licensing.

Lines 17 and 18 create a JFrame with a particular size. This frame contains a content pane to hold the sphere, and in line 19 that sphere is added to its center through a newly created instance of a GlobeBean. The GlobeBean displays the sphere and reacts to window resizes. Later you will add Earth texture and make the sphere more interactive, like a globe.

Shutting down ArcObjects is done by calling the AoInitialize.shutdown() method. Because this is a Swing application, you don't want to call shutdown at the end of this method. Instead, you call it when the window closes. Lines 20 through 31 illustrate this.

 

Template code for creating your own application

This section provides some template code to help you start writing your own applications. There are two general types of ArcGIS Engine-based Java applications—those that use the ArcGIS visual JavaBeans for GUI applications and those that do not. An application displaying a globe or a map uses visual beans and is usually a Swing GUI application. An application that does some analysis on data may not need visual beans and may write or display data non-graphically.

Non-visual application template

[Java]
Example 2 - Template code for an ArcGIS Engine application that doesn't utilize the ArcGIS visual JavaBeans

 1 import java.io.IOException;
 2 import com.esri.arcgis.system.AoInitialize;
 3 import com.esri.arcgis.system.EngineInitializer;
 4 import com.esri.arcgis.system.esriLicenseProductCode;
 5
 6 public class EngineTemplate {
 7     public static void main(String[] args) {
 8         try {
 9             EngineInitializer.initializeEngine();
10             new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
11             //
12             // Do something interesting here
13             //
14             System.out.println("Hello, ArcObjects!");
15         }
16         catch (IOException ex) {
17             System.out.println(ex.getMessage());
18             System.out.println("App failed.");
19         }
20         finally {
21             try {
22                 new AoInitialize().shutdown();
23             }
24             catch (IOException ex) {
25                 ex.printStackTrace();
26             }
27         }
28     }
29 }

Here is the output from this template:

Hello, ArcObjects!

As you can see, line 8 begins a try block surrounding the initialization steps, and anything else you may want to do in your application. Note that the caught exception at line 16 is an IOException. Nearly all ArcObjects exceptions thrown in Java are either an IOException or AutomationException, which is a subclass of IOException. You may want to be more or less specific in your exception handling, especially if you are working with ArcGIS Server.

The shutdown call at line 22 is in a finally block to ensure that it is called. AoInitialize is a singleton class and so you need not worry that you're shutting down a different system than the one you initialized at line 10. However, if you prefer, you could save a reference to the AoInitialize object created at line 10 and use it to call shutdown().

GUI application template

[Java]
Example 3 - Template code for an ArcGIS Engine application that utilizes the ArcGIS visual JavaBeans

 1 import java.awt.event.WindowAdapter;
 2 import java.awt.event.WindowEvent;
 3 import java.io.IOException;
 4 import javax.swing.JFrame;
 5 import com.esri.arcgis.system.AoInitialize;
 6 import com.esri.arcgis.system.EngineInitializer;
 7 import com.esri.arcgis.system.esriLicenseProductCode;
 8
 9 public class EngineVisualBeansTemplate extends JFrame {
10     //
11     // Create and display the frame
12     //
13     private void display() {
14         setSize(300, 200);
15         //
16         // Shutdown ArcObjects when the window closes.
17         //
18         addWindowListener(new WindowAdapter() {
19             public void windowClosing(WindowEvent e) {
20                 try {
21                     new AoInitialize().shutdown();
22                     System.exit(0);
23                 }
24                 catch (IOException ex) {
25                     System.out.println(ex.getMessage());
26                     System.exit(1);
27                 }
28             }
29         });
30         setVisible(true);
31     }
32
33     public static void main(String args[]) {
34         try {
35             EngineInitializer.initializeVisualBeans();
36             new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
37             EngineVisualBeansTemplate thisApp = new EngineVisualBeansTemplate();
38             thisApp.setTitle("Hello ArcObjects!");
39             thisApp.display();
40         }
41         catch (IOException ex) {
42             System.out.println(ex.getMessage());
43         }
44     }
45 }

Example 3 above is template code for a visual beans Swing application built with ArcObjects. Figure 2 below shows its output.

Figure 2 - Visual Beans Template Output

The essential elements of this template, and the non-visual beans template, are the same—they initialize and they shut down. In this example, lines 35 and 36 initialize the program while lines 18 through 29 show how to shutdown ArcObjects when the program exits due to a window closing event.

 

Considerations when working ArcObjects

When working with ArcGIS Engine using its Java API, objects execute in a Java Virtual Machine (JVM) and communicate via Java Native Interface (JNI) with native ArcObjects running outside the JVM. The consequence of this separation is that on the Java side you are generally working with proxy objects that reference native ArcObjects. This influences the manner in which your applications perform type checking and type conversions (or "casting").

Nearly all Java methods in ArcObjects return interfaces and take interfaces as parameters. Additionally, nearly all methods are defined in interfaces, rather than in classes. Consequently, your code will sometimes need to convert one interface (object) to another interface (object), or an interface (object) to a base class (object), in order to gain access to a particular method. Both conversions require constructors. A proxy constructor converts, or casts, an interface object to another interface object. A class (non-proxy) constructor converts, or casts, an interface object to a class object.

Casting of one object type to another is possible when the objects are related by extension or implementation, but this type of conversion is seldom done in ArcObjects because most Java classes in ArcObjects are proxies. The Java instanceof operator is of little use for this reason.

Here are examples of the two conversion patterns:

  1. Proxy constructor conversion:

    Interface2 interface2Obj = new Interface2ProxyClass(interface1Obj)

    This kind of operation is possible when a class that implements both interface objects' interfaces, references the proxy class. An example is:

    IGeometry iGeometry = new IGeometryProxy(iPoint);

    where iPoint is an IPoint, and IPoint and IGeometry are both implemented by Point, which contains a member field reference to an IGeometryProxy.

  2. Class (non-proxy) constructor conversion:

    AClass aClassInstance = new AClass(interfaceObj);

    This kind of operation is possible when AClass implements interfaceObj's interface. An example is:

    Point point = new Point(iPoint);

    where iPoint is a returned object of type IPoint.

This, of course, raises the question 'How do you know what you can convert from, and to?'. When you have a reference to an object returned to you from an ArcObjects method call, you may have access to a method that gets its related type, such as the IGeometry.getGeometryType() method. When such a method is unavailable, there are two ways to know what to convert—informed guessing, and programmatic trial and error. The former is usually all you need.

Another example—Hello, Centroid!

Example 4 is a program showing type conversions. It prints the coordinates of a centroid for the first feature in a shapefile containing polygonal features. Assuming CLASSPATH is set properly, you just need to supply the path and name of a shapefile as command line arguments like this:

This yields output similar to this:

Hello, Centroid! Centroid: -120.42802745036587, 47.376761952973496 Centroid: -120.42802745036587, 47.376761952973496

[Java]
Example 4 - HelloCentroid.java: A program showing type conversions

  1 import java.io.IOException;
  2 import com.esri.arcgis.datasourcesfile.ShapefileWorkspaceFactory;
  3 import com.esri.arcgis.geodatabase.FeatureClass;
  4 import com.esri.arcgis.geodatabase.IFeature;
  5 import com.esri.arcgis.geodatabase.IFeatureClass;
  6 import com.esri.arcgis.geodatabase.IFeatureWorkspace;
  7 import com.esri.arcgis.geodatabase.IFeatureWorkspaceProxy;
  8 import com.esri.arcgis.geodatabase.IWorkspace;
  9 import com.esri.arcgis.geometry.IArea;
 10 import com.esri.arcgis.geometry.IAreaProxy;
 11 import com.esri.arcgis.geometry.IGeometry;
 12 import com.esri.arcgis.geometry.IPoint;
 13 import com.esri.arcgis.geometry.Polygon;
 14 import com.esri.arcgis.geometry.esriGeometryType;
 15 import com.esri.arcgis.system.AoInitialize;
 16 import com.esri.arcgis.system.EngineInitializer;
 17 import com.esri.arcgis.system.esriLicenseProductCode;
 18
 19 public class HelloCentroid {
 20
 21     private FeatureClass getFeatureClass(String path, String name) throws IOException {
 22         FeatureClass featureClass = null;
 23         try {
 24             //
 25             // Create a ShapefileWorkspaceFactory and get a workspace from it.
 26             //
 27             ShapefileWorkspaceFactory shapefileWorkspaceFactory = new ShapefileWorkspaceFactory();
 28             IWorkspace workspace = shapefileWorkspaceFactory.openFromFile(path, 0);
 29             //
 30             // Convert it to a feature workspace and get a feature class from it.
 31             //
 32             IFeatureWorkspace featureWorkspace = new IFeatureWorkspaceProxy(workspace);
 33             IFeatureClass iFeatureClass = featureWorkspace.openFeatureClass(name);
 34             featureClass = new FeatureClass(iFeatureClass);
 35         }
 36         catch (IOException e) {
 37             System.out.println("Could not open shapefile: " + name);
 38             throw e;
 39         }
 40         return featureClass;
 41     }
 42
 43     private void printFirstFeatureCentroid(FeatureClass featureClass) throws IOException {
 44         IPoint centroid = null;
 45         //
 46         // Get the first feature in the class.
 47         //
 48         IFeature feature = featureClass.getFeature(0);
 49         //
 50         // Get the shape of the feature.
 51         //
 52         IGeometry geometryShape = feature.getShape();
 53         //
 54         // If the feature is polygonal, convert its shape to an area and get the centroid.
 55         //
 56         if (featureClass.getShapeType() != esriGeometryType.esriGeometryPolygon) {
 57             throw new IOException("Feature class does not contain polygonal features.");
 58         }
 59         IArea area = new IAreaProxy(geometryShape);
 60         centroid = area.getCentroid();
 61         System.out.println("Centroid: " + centroid.getX() + ", " + centroid.getY());
 62         //
 63         // Or, convert the shape to polygon and get the centroid.
 64         //
 65         Polygon polygon = new Polygon(geometryShape);
 66         centroid = polygon.getCentroid();
 67         System.out.println("Centroid: " + centroid.getX() + ", " + centroid.getY());
 68     }
 69
 70     public static void main(String[] args) {
 71         System.out.println("Hello, Centroid!");
 72         if (args.length != 2) {
 73             System.out.println("Usage: HelloCentroid  ");
 74             System.exit(1);
 75         }
 76         try {
 77             EngineInitializer.initializeEngine();
 78             new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
 79             HelloCentroid thisApp = new HelloCentroid();
 80             //
 81             // Get the feature class for the path and name specified,
 82             // and get its first feature's centroid.
 83             //
 84             FeatureClass featureClass = thisApp.getFeatureClass(args[0], args[1]);
 85             thisApp.printFirstFeatureCentroid(featureClass);
 86         }
 87         catch (IOException ex) {
 88             ex.printStackTrace();
 89             System.out.println("App failed.");
 90         }
 91         finally {
 92             try {
 93                 new AoInitialize().shutdown();
 94             }
 95             catch (IOException ex) {
 96                 ex.printStackTrace();
 97             }
 98         }
 99     }
100 }

 

The HelloCentroid example expects to work with a shapefile containing polygonal features, and its purpose is to get the centroid of the first feature and print it.

Features come from feature classes, and the getFeatureClass method starting at line 21 returns a FeatureClass object given the path to a shapefile and the shapefile's name.

Within this method, a ShapefileWorkspaceFactory is created at line 27. Calling its openFromFile() method at line 28 returns an IWorkspace object. You know you are working with features, and you eventually want to get to a feature class, so at line 32 workspace is converted to an IFeatureWorkspace type by the proxy constructor for IFeatureWorkspaceProxy. IFeatureWorkspaceProxy is a class that implements IFeatureWorkspace, and only that interface. Therefore the result is assigned to that interface type without loss of method access.

From the feature workspace, at line 33, calling openFeatureClass returns an IFeatureClass object, which has access to the desired getFeature() method. Then at line 34 that object is used to get its FeatureClass instance.

The method needn't have gone that far. It could have returned an IFeatureClass object and the program would have worked. The reason for converting it to a FeatureClass is two fold: The first is to show another type of conversion (a non-proxy class constructor conversion), and the second is to make the point that now this method could be used in a program that not only wanted to get features, but also wanted to do dataset analysis, or dataset editing, or feature class management, or several other things—all of which come from different interfaces that FeatureClass implements. Once you have a FeatureClass object you can do all of these things, whereas returning an IFeatureClass object limits its use to the methods of IFeatureClass.

The printFirstFeatureCentroid method starts at line 43. It takes a FeatureClass object as a parameter, and uses that object, at line 48, to get its first feature. The getFeature() method returns an IFeature (interface) object rather than a Feature (class) object. That object could have been converted to a Feature object with this line:

Feature feature = new Feature(featureClass.getFeature(0));

but since this program only needs the feature's shape, which comes from calling getShape() defined in the IFeature interface, no conversion is done. Had the program instead wanted to split the feature and then get its centroid it would have needed access to the IFeatureEdit interface (to call split()), in which case the conversion above would have been appropriate.

Line 52 shows that calling getShape() returns an IGeometry object representing the feature's shape.

At line 56 the program checks that the shape is polygonal by calling getShapeType on the feature class. A feature class can contain only one feature type, which means only one shape type. The result is compared against the defined value for polygons and an exception is thrown if the returned type is unexpected.

IArea is the only interface that declares the getCentroid() method. If you can get an IArea object, you can call getCentroid, which is what lines 59 and 60 do, which shows the proxy constructor conversion pattern. That proxy constructor creates an IAreaProxy object using geometryShape, and assigns it to an IArea. IArea is then used to call getCentroid() to get the centroid, which is used to print its coordinates at line 61

But Polygon implements IArea, and so if you can get a Polygon from the IGeometry, you could instead use it to get the centroid. This is what lines 65 and 66 do, just to show the other conversion pattern. The Polygon class constructor along with geometryShape creates a Polygon instance, from which getCentroid() is called at line 66.

Either conversion pattern works in this case since the only method to be called is getCentroid(), and therefore there's no advantage either way. If you had additionally wanted to get access to the points of the polygon, you would have wanted to convert directly to the Polygon to access the methods in the IPointCollection interface, which Polygon implements. There is another consideration for which pattern to use. Under some conditions, for example if you were getting the centroid of a large number of feature polygons you might choose to use the proxy constructor pattern, as there is less overhead. For a few hundred features, or maybe even a few thousand features, you would probably notice no difference. But in the millions you might. Your particular environment might vary, so do some tests to find out which conversion is best for you.

But how would you know that you could do either of these conversions? How would you know you could get an area or a polygon from a shape? You might assume that the shape returned from a polygonal feature is a polygon, and because Polygon implements both IGeometry and IArea you could do either of these conversions. The only way to know you can do these conversions is to try them. The conversion itself will not throw an exception, but if your conversion is wrong, when you try to use the converted object it may throw an exception. The exception thrown will be an AutomationException with a message stating, "No such interface supported", and a code of 2147500034.

 

More about working with ArcObjects

The HelloCentroid program points out a few things that a new ArcObjects developer might find different from typical Java programs. Here are some other things to be aware of when you write your ArcObjects-based applications or libraries:

  1. On non-Windows platforms you may need to call mwcleanup, (which is located on your PATH after sourcing init_engine) if your application does not exit cleanly.
  2. Don't use the default constructor for proxy classes, even though they are public. Their purpose is to convert interface objects to other interface objects.
  3. The Object Model Diagrams, Library Reference material, and javadocare all written with language-neutral terminology and constructs which may appear strange to a Java developer. This includes the following:
    • On the OMD's, properties are available through method calls in the Java API, usually as "get", "set", or "is" methods.
    • Native ArcObjects methods that return multiple values using "out" parameters have two possible counterparts in Java: The first is that there may be a set of Java methods that return the individual values. So check the javadoc. The second is a method that accepts single-element arrays, one per value, simulating "out" parameters. This array element may contain an object or even an array of objects.
    • Native ArcObjects has a VARIANT type. The Java API uses the Object class in place of VARIANTs and client software is expected to do the proper casting.
    • Native ArcObjects use C structs. The correspondence in Java is a class containing public instance variables matching the member elements of the struct. The naming convention is to prefix an underscore character for the struct's name. In Native ArcObjects a struct Foo has a corresponding Java class _Foo.
    • Native ArcObjects use C enums. The corresponding Java API implementation uses interfaces with public static final int fields. The naming convention is to retain the same name, although not capitalized.

 

OMDs

If you use Object Model Diagrams (OMD's) you will need to know how they translate into Java code that utilizes ArcObjects. Figure 3 is a portion of an OMD for BasicTableHistogram.

Figure 3 - BasicTableHistogram OMD

Shaded 3D boxes like this one correspond to ArcObjects classes. This box shows that BasicTableHistogram implements four interfaces, and the one shown is IBasicHistogram. This particular interface indicates there are two settable properties, CustomMax and CustomMin. OMD properties generally correspond to Java accessor methods and these two properties correspond to two Java accessor methods: setCustomMax(double) and setCustomMin(double). It also shows three other methods that can be called, one of which corresponds to the Java method getHistogram(). This method takes two parameters and returns a Java boolean. he two parameters listed are "out" parameters of type Variant. An "out" parameter is always handled by a single element array, and a Variant is always handled by an Object. Therefore, the translation from the OMD to Java for this method is:

boolean getHistogram(Object[] doubleArrayValues, Object[] longArrayFrequencies)

The first elements of the Object arrays are arrays themselves. The names also say they hold doubles and longs. The translation into Java is double and int.

 

Javadoc

Javadoc is an indispensable tool for writing ArcObjects-based applications, and it provides other helpful information that is not contained in the OMDs, but its contents also require translation because portions of it come from a language-neutral repository of component help. Javadoc 1 shows the javadoc for the getHistogram method. The description "Histogram as an array of values (doubles) and a paired array of frequencies (longs)" comes from the component help, which explains why it does not exactly match with the Java API to ArcObjects, as is shown in Example 5.

Javadoc 1 - Method example from javadoc

Example 5 is an example method showing how to use the information gleaned from the OMD and the javadoc. Note the following:

Object arrays oValues and oFrequencies are created with one element each to hold the results of calling getHistogram. These results are accessed through index 0 and cast to arrays of doubles and ints. These arrays are then iterated through and their values printed.

[Java]
Example 5 - getHistogram translation

    private void printHistogram(BasicTableHistogram basicTableHistogram) throws IOException {
        Object[] oValues = {null};
        Object[] oFrequencies = {null};
        double[] values = null;
        int[] frequencies = null;
        boolean isSampled = false;

        isSampled = basicTableHistogram.getHistogram(oValues, oFrequencies);
        values = (double[]) oValues[0];
        frequencies = (int[]) oFrequencies[0];

        System.out.println((isSampled ? "Sampled" : "Unsampled" + " data..."));
        System.out.print("    Value:\t");
        for (int i = 0; i < values.length; i++) {
            System.out.print(values[i] + "\t");
        }
        System.out.println();
        System.out.print("Frequency:\t");
        for (int i = 0; i < frequencies.length; i++) {
            System.out.print(frequencies[i] + "\t");
        }
        System.out.println();
    }

 

Hello, Globe! example

Example 6 is an interactive version of the HelloSphere program called HelloGlobe to show some additional Swing/bean interaction, namely rotating, zooming, and resetting the view of the texture wrapped sphere, making it look and act more like a globe. For more advanced Swing applications, refer to the article ArcGIS development using visual JavaBeans for important issues regarding Java, ArcObjects, and Swing interaction.

To apply texture to the globe, click on the folder icon, which represents the open document command, and find a .3dd file. The output shown in Figure 3 uses the World.3dd file found in the ZIP file accompanying this article. The navigational button, next to the folder icon, allows you to zoom and rotate/pan with the left and right mouse buttons when mousing the globe. The last button, overview, will return the globe to its default position.

[Java]
Example 6 - HelloGlobe.java: A program to display an interactive globe

 1 import java.awt.BorderLayout;
 2 import java.awt.event.WindowAdapter;
 3 import java.awt.event.WindowEvent;
 4 import java.io.IOException;
 5 import javax.swing.JFrame;
 6
 7 import com.esri.arcgis.beans.TOC.TOCBean;
 8 import com.esri.arcgis.beans.globe.GlobeBean;
 9 import com.esri.arcgis.beans.toolbar.ToolbarBean;
10 import com.esri.arcgis.globecore.ControlsGlobeFullExtentCommand;
11 import com.esri.arcgis.globecore.ControlsGlobeNavigateTool;
12 import com.esri.arcgis.globecore.ControlsGlobeOpenDocCommand;
13 import com.esri.arcgis.system.AoInitialize;
14 import com.esri.arcgis.system.EngineInitializer;
15 import com.esri.arcgis.system.esriLicenseProductCode;
16
17 public class HelloGlobe extends JFrame {
18     //
19     // Create and display the frame
20     //
21     private void display() throws IOException {
22         setSize(500, 400);
23         //
24         // Create the globe, toolbar, and table of contents beans.
25         //
26         GlobeBean globeBean = new GlobeBean();
27         ToolbarBean toolbarBean = new ToolbarBean();
28         TOCBean tocBean = new TOCBean();
29         //
30         // Add beans to the content pane.
31         //
32         getContentPane().add(toolbarBean, BorderLayout.NORTH);
33         getContentPane().add(globeBean, BorderLayout.CENTER);
34         getContentPane().add(tocBean, BorderLayout.WEST);
35         //
36         // Add commands and tool to the toolbar.
37         //
38         toolbarBean.addItem(new ControlsGlobeOpenDocCommand(), 0, -1, false, 0, 1);
39         toolbarBean.addItem(new ControlsGlobeNavigateTool(), 0, -1, false, 0, 1);
40         toolbarBean.addItem(new ControlsGlobeFullExtentCommand(), 0, -1, false, 0, 1);
41         //
42         // Buddy up the globe with the toolbar and table of contents.
43         //
44         toolbarBean.setBuddyControl(globeBean);
45         tocBean.setBuddyControl(globeBean);
46         //
47         // Shutdown ArcObjects when the window closes.
48         //
49         addWindowListener(new WindowAdapter() {
50             public void windowClosing(WindowEvent e) {
51                 try {
52                     new AoInitialize().shutdown();
53                     System.exit(0);
54                 }
55                 catch (IOException ex) {
56                     System.out.println(ex.getMessage());
57                     System.exit(1);
58                 }
59             }
60         });
61         setVisible(true);
62     }
63
64     public static void main(String args[]) {
65         try {
66             EngineInitializer.initializeVisualBeans();
67             new AoInitialize().initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
68             HelloGlobe thisApp = new HelloGlobe();
69             thisApp.setTitle("Hello, Globe!");
70             thisApp.display();
71         }
72         catch (IOException ex) {
73             System.out.println(ex.getMessage());
74         }
75     }
76 }

Here is the output from this example:

Figure 3 - HelloGlobe output

 

Discussion

The significant parts of this program are as follows:

Lines 26 through 28 create the beans we will use. The GlobeBean supports globe management, display, events, camera positions, etc. The ToolbarBean hosts a panel of commands and a tool. The TOCBean is the table of contents view of layers that will be added to the globe.

Lines 32 through 34 add these beans to the JFrame's content pane.

Lines 38 through 40 add two commands and one tool to the toolbar. The first is a command to display a dialog to get a .3dd file to texture the globe. The second is a tool to zoom and rotate the globe. The third is a command that causes the globe to return to its default position.

Line 44 and 45 establish the connection between the globe and the toolbar and table of contents so that when you press a command or tool icon, or when you click on layers in the table of contents, the globe responds.

Lines 49 through 60, as discussed in previous examples, calls shutdown() when the window closes.

 

Summary

This article presented some relatively simple ArcObjects examples to get you up and running and explain a few concepts unique to the API. It talked about how to compile and run the examples, by telling you about the necessary jar files and gave you a couple of templates from which to grow. t talked about the need to do type conversions on interface objects returned from methods and how to use proxy and non-proxy constructors to do that. It went through some of the reasoning involved in getting to data you may want. It mentioned some other things to watch out for, like using single dimension arrays for out parameters, and Object/variant casting. It provided references to the library overviews, and javadoc. Finally to help you choose a direction for further discovery, this article concludes with a brief description of the Java packages comprising ArcObjects.

 

Java packages summary

The ArcObjects API is divided into a number of libraries; the example code in this article used a few of them. Each of the ArcObjects libraries has associated library overview documentation that is part of the developer kit, and these libraries have Java package counterparts, which have javadoc descriptions.

The following list of available Java packages is organized into their corresponding ArcObjects libraries.