ldonahue

ArcObjects and SOEs in ArcGIS Server 10.2

Discussion created by ldonahue on Sep 4, 2013
Am I correct in my understanding that at 10.2, the only way to run ArcObjects in the Server is in the SOE, not in the SOAP client?

The examples I'm seeing for SOEs in 10.2 use a client stub and the instance of the stub calls methods in the SOE. 

Creating an instance of IMapServerInfo in the SOAP client is something that we should "not" be trying to do?  Is that correct?

The reason I ask is that I have read that you cannot do MXD related things in SOEs suchh as use IMap, ILayer, etc, but when you try to provide a public contract in the SOE interface for returning a IMapServer, you also get nice warnings about not being able to do that.

The SimpleSOAPSOE sample implementation is shown below.

The SOE Interface:
import com.esri.arcgis.interop.extn.ArcGISExtension;

@ArcGISExtension
public interface ISimpleSOAPSOE {
    public int getMapLayerInfoByName(String name);
    public int getMayLayerInfosCount();
    public String printMapLayerInfoFieldNames(int maplayerinfoindex);
}


The SOE Bean:
import java.io.IOException;

import com.esri.arcgis.geodatabase.IFields;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.server.IServerObjectExtension;
import com.esri.arcgis.server.IServerObjectHelper;
import com.esri.arcgis.server.SOAPRequestHandler;
import com.esri.arcgis.system.ILog;
import com.esri.arcgis.system.ServerUtilities;
import com.esri.arcgis.interop.extn.ServerObjectExtProperties;
import com.esri.arcgis.carto.IMapLayerInfos;
import com.esri.arcgis.carto.IMapServer3;
import com.esri.arcgis.carto.IMapServerDataAccess;
import com.esri.arcgis.carto.IMapServerInfo;

@ArcGISExtension
@ServerObjectExtProperties(displayName = "SimpleSOAPSOE", description = "My simple SOAP SOE")
public class SimpleSOAPSOE extends SOAPRequestHandler implements IServerObjectExtension, ISimpleSOAPSOE {
    
    private static final long serialVersionUID = 1L;
    
    private ILog serverLog;
    
    private IMapServerDataAccess mapServerDataAccess;
    private IMapServer3 mapServer;
    private IMapServerInfo mapServerInfo;
    private IMapLayerInfos mapLayerInfos;

    public SimpleSOAPSOE() throws Exception {
        super();
    }


    /**
     * init() is called once, when the instance of the SOE is created. 
     */
    public void init(IServerObjectHelper soh) throws IOException, AutomationException {
        /*
         * An SOE should retrieve a weak reference to the Server Object from the Server Object Helper in
         * order to make any method calls on the Server Object and release the
         * reference after making the method calls.
         */
        this.serverLog = ServerUtilities.getServerLogger();
        this.serverLog.addMessage(3, 200, "Initialized " + this.getClass().getName() + " SOE.");
        
        this.mapServerDataAccess = (IMapServerDataAccess) soh.getServerObject();
        
        this.mapServer = (IMapServer3)this.mapServerDataAccess;
        this.mapServerInfo = mapServer.getServerInfo(mapServer.getDefaultMapName());
        this.mapLayerInfos = mapServerInfo.getMapLayerInfos();
    }

    /**
     * shutdown() is called once when the Server Object's context is being shut down and is about to go away.
     */
    public void shutdown() throws IOException, AutomationException {
        /*
         * The SOE should release its reference on the Server Object Helper.
         */
        this.serverLog.addMessage(3, 200, "Shutting down "
                + this.getClass().getName() + " SOE.");
        this.serverLog = null;
        
        this.mapServer = null;
        this.mapServerInfo = null;
        this.mapLayerInfos = null;
        this.mapServerDataAccess = null;
    }
    
    /**
     * Method to get the MapLayerInfo index by name, rather than getting it from the REST directory
     */
    public int getMapLayerInfoByName(String name){
        
        int index = 0;
        
        try {
            for(int i = 0; i < mapLayerInfos.getCount(); i++){
                if(mapLayerInfos.getElement(i).getName().equalsIgnoreCase(name)){
                    index = i;
                    break;
                }
            }
        } catch (AutomationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return index;
    }
    
    /**
     * Method to get the count of all Map Layer Info objects
     */
    public int getMayLayerInfosCount(){
        int count = 0;
        try {
            count = mapLayerInfos.getCount();
        } catch (AutomationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return count;
    }
    
    /**
     * Method to iterate over and print the field names of a MapLayerInfo object by supplying 
     * the MapLayerInfos element index.
     */
    public String printMapLayerInfoFieldNames(int maplayerinfoindex){
        
        StringBuilder fieldList = new StringBuilder();
        
        try {
            IFields fields = mapLayerInfos.getElement(maplayerinfoindex).getFields();
            
            for(int i = 0; i < fields.getFieldCount(); i++){
                fieldList.append(fields.getField(i).getName() + " ");
            }
        } catch (AutomationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return fieldList.toString();
    }

}


The SOAP Client:
import package.name.SimpleSOAPSOEServiceBindingStub;

public class SimpleSOAPSOEClient {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        String serviceName = "mapservicedirectory/mapservicename";
        String url = "http://servername:6080/arcgis/services/" + serviceName + "/MapServer/SimpleSOAPSOE";
        
        SimpleSOAPSOEServiceBindingStub stub = new SimpleSOAPSOEServiceBindingStub(url);
        
        // Note: the actual layer name in the .msd and REST directory is "Parcels"
        int layerId = stub.getMapLayerInfoByName("parcels");
        
        System.out.println("The layer index of the parcel layer is: " + layerId);
        
        System.out.println("The layer count in this map service is: " + stub.getMayLayerInfosCount());
        
        System.out.println("The field names in the parcel layer are: " + stub.printMapLayerInfoFieldNames(layerId));
        
    }

}


The output:

The layer index of the parcel layer is: 7
The layer count in this map service is: 34
The field names in the parcel layer are: OBJECTID APN APN2 PARCEL Shape Shape.STArea() Shape.STLength() 

Outcomes