Consuming Server Object Extensions


Once a SOE has been developed and successfully deployed and registered with ArcGIS Server, it is ready to be consumed by a client application.  There are multiple ways to consume SOE’s.  The most typical approaches will be through console applications and/or web applications. 

Console Application


To access your SOE in a console based application you need to obtain the Server Context, access the Server Object through the service context, then call the findExtensionByTypeName(soeName) on the MapServer.  

Whatever is returned by findExtensionByTypeName() can be collected as IServerObjectExtension and this reference can be used to call a method on the SOE.  Below is a basic diagram of the relationships between a mock SOE class and ISoeInterface interface and the ArcObjects classes/interfaces. 

HelloWorldSOE console client

Once you have successfully developed, deployed, registered, and enabled your HelloWorldSOE, we can create clients to access it from the ServerObject you enabled it on.  Below is a sample console client code which creates a connection to an ArcGIS Server context and MapServer Object, accesses the HelloWorldSOE through the IServerObjectExtensionManager interface and consumes the HelloWorldSOE to print out the message. 
[Java]
package soe.client;

import demo.IHelloWorldSOE;
import com.esri.arcgis.carto.MapServer;
import com.esri.arcgis.server.IServerObjectExtension;
import com.esri.arcgis.server.IServerObjectExtensionManager;
import com.esri.arcgis.server.ServerConnection;
import com.esri.arcgis.server.ServerContext;
import com.esri.arcgis.server.ServerObjectManager;
import com.esri.arcgis.system.ServerInitializer;
public class HelloWorldClient{
    public static void main(String[] args){

        ServerInitializer si = new ServerInitializer();
        si.initializeServer(domain, user, password);
        System.out.print("Connecting to ArcGIS Server...");

        try{
            connection = new ServerConnection();
            connection.connect(serverName);
            System.out.println("Done.");

            //Retrieve the SOM to get ServerContext and the Map Server Object
            System.out.print("\nRetrieving Server Object Manager.");
            ServerObjectManager som = new ServerObjectManager
                (connection.getServerObjectManager());
            System.out.println("Done.");

            String soeName = "HelloWorldSOE";
            String serviceName = "USA_DEMO";

            ServerContext serverContext = new ServerContext(som.createServerContext
                (serviceName, "MapServer"));
            MapServer mapServer = (MapServer)serverContext.getServerObject();

            //Access the soe through the IServerObjectExtensionManager
            System.out.print("\nObtaining reference to SOE..");
            IServerObjectExtensionManager extnMgr = (IServerObjectExtensionManager)
                mapServer;
            IServerObjectExtension helloWorldSOE = extnMgr.findExtensionByTypeName
                (soeName);
            System.out.println("Done. Found " + soeName + ".");

            //Consume the SOE
            System.out.println("\nInvoking SOE's \"Hello World\" functionality..");
            IHelloWorldSOE mySOE = (IHelloWorldSOE)helloWorldSOE;
            String response = mySOE.helloWorld();
            System.out.println("Message from SOE = " + response);

        }
        catch (Exception e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private static String domain = "localhost";
    private static String user = "sde";
    private static String password = "sde";
    private static String serverName = "localhost";

    private static ServerConnection connection;
}
In order to use the client code in your environment, you will need to change the appropriate server credentials to match your environment. 

Web ADF

The WebADF references GISResources, as well as attributes to GIS business objects like WebMap, through the WebContext.  Once you have access to the Server Object through the WebContext the pattern of obtaining your SOE is the same as in a console application. 
The example code snippet is passed a WebContext as a parameter then gets access to the Server Object for to access an SOE: 
[Java]
public void accessSOE(WebContext context, String soeName){
    AGSLocalMapResource localMapRes = (AGSLocalMapResource)context.getResources()
        .get("ags1");
    MapServer mapServer = localMapRes.getLocalMapResource();


    // Access your SOE through ISOEMgr
    IServerObjectExtensionManager extnMgr = (IServerObjectExtensionManager)mapServer;
    IServerObjectExtension SOE = extnMgr.findExtensionByTypeName(soeName);
}
In the code snippet above, "ags1" is the managed bean name defined in your web application's faces-config file for managed bean class AGSLocalMapResource.  There are multiple ways to include this type of business logic into your WebADF web application.  One of the simplest ways is to add a JSF actionListener tag in a JSP that can respond to user events in your JSF page.  The following are code snippets to access a registered SOE named MySOE.  First you need to add a JSF commandButton and JSF actionListener to your JSF page: 
[HTML]
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
 ...
    <h:commandButton value="Access SOE">
       <f:actionListener type="demo.MySoeListener"/>
    </h:commandButton>


 
When a user clicks the button the application will fire an event handled by application code in a class that implements JSF's ActionListener interface and the processAction method.  You can perform any processing you need to inside this method and it must accept an ActionEvent as its only parameter.  We will use the action listener to obtain the WebContext from the ActionEvent and then pass the WebContext to a managed bean for access to our SOE. 
[Java]
package demo;

public class MySoeListener implements ActionListener{

    private static WebContext context;

    public void processAction(ActionEvent event)throws AbortProcessingException{
        context = (WebContext)WebUtil.getWebContext(event.getComponent());
        MySoeBean mySoe = new MySoeBean();
        mySoe.accessSOE(context, "HelloWorldSOE");
    }
}
[Java]
package demo;

public class MySoeBean{

    public void accessSOE(WebContext context, String soeName){
        AGSLocalMapResource localMapRes = (AGSLocalMapResource)context.getResources()
            .get("ags1");
        MapServer mapServer = localMapRes.getLocalMapResource();

        // Access your SOE through ISOEMgr
        IServerObjectExtensionManager extnMgr = (IServerObjectExtensionManager)
            mapServer;
        IServerObjectExtension SOE = extnMgr.findExtensionByTypeName(soeName);
        serverLog.addMessage(1, 10801, "Found " + soeName);
    }
Although not required by this approach, it is good practice to add the MySoeBean as a managed bean in your faces-config.xml file. 
[XML]
<managed-bean>
  <managed-bean-name>soeBean</managed-bean-name>
  <managed-bean-class>demo.MySoeBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>