To handle SOAP requests in an SOI, you must implement I and I. These interfaces contain two methods, handle and handle, which allow you to intercept SOAP requests and execute your own business logic.
The handle method handles all the SOAP binary requests that come from ArcObjects-based clients, such as ArcMap, ArcGIS Engine, or custom ArcObjects applications. For example, accessing and rendering a map service on ArcMap makes the requests come through the handle method.
The handle method handles all the SOAP XML string requests that come from non-ArcObjects-based clients, such as requests made via SOAP SDK.
To preprocess the SOAP request, you must unpack the incoming request, customize the request parameters, repack the request, and send it to the underlying service object for processing. Similar procedure also applies to postprocessing responses. To postprocess the SOAP response, you must unpack the response, customize the response content, repack the response to appropriate format, and send it back to the client. The SDK contains utility classes to assist with packing and unpacking the relevant request and response objects.
This topic demonstrates the workflows for handling SOAP binary requests using the handle method and SOAP string requests using the handle method.
Use the handle Binary Request() method
The following code in the handle method is automatically generated if you create an SOI from soi-archetype.
public byte[] public byte[] handleBinaryRequest(byte[] request) throws IOException, AutomationException {
serverLog.addMessage(3, 200, "Request received in Sample Object Interceptor for handleBinaryRequest");
IRequestHandler requestHandler = soiHelper.findRequestHandlerDelegate(so);
if (requestHandler != null) {
return requestHandler.handleBinaryRequest(capabilities, request);
}
return null;
}Once a SOAP binary request is received, the above handle function will be triggered, and its request variable will be populated with the request information, such as request name and request parameters. Based on these variables, the I method will generate the response, which is also a byte array.
The following code snippet demonstrates how to preprocess a SOAP binary request. It keeps only the first layer visible for the export operation of a map service, no matter how many layers exist in the map service.
To achieve this function, you must find the parameter that controls the layer visibility for the export operation. Based on SOAP SDK, the SOAP method for the export operation is ExportMapImage, whose input parameter Map defines the content of the map to be exported. One of Map's properties is Layer, which is an array of Layer with the set method to control the layer visibility. In this way, you can track down the objects to customize in the SOI.
Sample code:
public byte[] handleBinaryRequest(byte[] request) throws IOException, AutomationException {
IRequestHandler requestHandler = soiHelper.findRequestHandlerDelegate(so);
if (requestHandler != null) {
IMessage requestMessage = SOIHelper.convertBinaryRequestToMessage(request);
String requestName = requestMessage.getName();
serverLog.addMessage(3, 200, "Request name is " + requestName); //about server logs, please refer to topic: how to audit requests in SOIs
if ("ExportMapImage".equals(requestName)) {
IXMLSerializeData requestParams = requestMessage.getParameters();
int mapDescriptionIndex = requestParams.find("MapDescription");
IMapDescription mapDescription = (IMapDescription)requestParams.getObject(mapDescriptionIndex, requestMessage.getNamespaceURI(), "MapDescription");
int layerCount = mapDescription.getLayerDescriptions().getCount();
for (int i= layerCount-1;i>0;i--) {
mapDescription.getLayerDescriptions().getElement(i).setVisible(false);
}
byte[] modifiedRequest = SOIHelper.convertMessageToBinaryRequest(requestMessage);
return requestHandler.handleBinaryRequest(modifiedRequest);
}
return requestHandler.handleBinaryRequest(request);
}
return null;
}The above code first calls the Soap method to convert the byte-array request to I, which provides access to the request name string and request parameters as IXML. Second, the IXML method is called to retrieve I, which is the input parameter to customize in this workflow. Then, I can be returned from the I array and I can be called. Last, the SOI method converts the modified request back to byte-array format. This modified byte-array request can then be passed to I for the service object to process and generate the corresponding response based on the modified request.
Postprocessing SOAP binary responses works in a similar way. First, you must obtain the byte-array response returned from the I method with either the original or modified request. Next, you will convert the byte-array response to I using the SOI method. The I interface provides access to the response content via I, which returns an object that can be cast to the IXML interface. Calling the IXML method will return the Result object. The Result object can be cast to the corresponding interface or class which provides access to the element for modification. After the response element is modified, you must convert it from I to a byte array by using SOI and return the byte-array response to the client.
To test the above code, you can deploy the SOI and enable the SOI with a map service. After you add the map service to ArcMap, only the first layer should display on the map. As this code only modifies ExportMapImage, to customize other SOAP methods, such as GetLegendInfo, you can refer to the Java layer access SOI sample.
Use the handle String Request() method
The following code in the handle method is automatically generated if you create an SOI from soi-archetype.
public String handleStringRequest(String capabilities, String request) throws IOException, AutomationException {
// Log message with server
serverLog.addMessage(3, 200, "Request received in Sample Object Interceptor for handleStringRequest");
// Find the correct delegate to forward the request too
IRequestHandler requestHandler = soiHelper.findRequestHandlerDelegate(so);
if (requestHandler != null) {
// Return the response
return requestHandler.handleStringRequest(capabilities, request);
}
return null;
}Unlike the handle method, handle intercepts all the SOAP requests that come from non-ArcObjects-based clients, such as XML requests sent to the service SOAP endpoint from custom applications using SOAP SDK.
When the request reaches the service SOAP endpoint, the handle method is triggered and the requests are directly passed in as the request string variable. Based on the request and capabilities variables, I generates the response, which is also an XML string.
To preprocess the SOAP string request, you will first convert the request string to I. Then, the request parameters can be accessed from the I method and cast to IXML, whose get method can be used to retrieve the underlying request object for modification. After the request object is modified, you must call the SOI method to copy a new I from the original one, and use the SOI method to commit the changes of the request object to the copied I, which can then be converted back to a string via SOI. This string can be passed to I for the service object to process and generate a response.
The same logic also applies to postprocessing SOAP string responses. In the following sample code, the SOI adds a custom message to the Comments property of the map service’s GetDocumentInfo response.
To customize this response, you must understand the response object type first. Based on SOAP SDK, the GetDocumentInfo method returns a Property which contains a Property named Comments. This Property can be accessed via I in Enterprise SDK and its value can be set by the I method. Note that the modified Property must be committed to I copied from the SOI method.
Sample code:
public String handleStringRequest(String capabilities, String request)
throws IOException, AutomationException {
// Find the correct delegate to forward the request too
IRequestHandler requestHandler = soiHelper.findRequestHandlerDelegate(so);
if (requestHandler != null) {
String response = requestHandler.handleStringRequest(capabilities, request);
IMessage responseMessage = SOIHelper.convertStringRequestToMessage(response);
if ("GetDocumentInfoResponse".equals(responseMessage.getName())) {
IXMLSerializeData orginalParams = responseMessage.getParameters();
int resultObjIndex = orginalParams.find("Result");
IPropertySet propSet = (IPropertySet)orginalParams.getObject(resultObjIndex,
responseMessage.getNamespaceURI(), "PropertySet");
propSet.setProperty("Comments", "Custom message from SOI.");
IMessage modifiedResponseMsg = soiHelper.createNewIMessage(responseMessage);
IXMLSerializeData modifiedData = modifiedResponseMsg.getParameters();
soiHelper.addObjectToXMLSerializeData("Result", propSet, "PropertySet", modifiedData);
String modifiedResponse = SOIHelper.convertMessageToStringRequest(modifiedResponseMsg);
return modifiedResponse;
}
// Return the response
return requestHandler.handleStringRequest(capabilities, request);
}
return null;
}In the above code, the request variable is directly passed to the I method to generate the raw response string. Then, by calling SOI, the raw response string is converted to I, which provides access to the response name and the response content as IXML.
As this code intercepts the response from the GetDocumentInfo method, the name of the response should be GetDocumentInfoResponse. Typically, the name of the response is the service’s SOAP method name with Response appended, and the name of the SOAP response content is Result. In this case, the Result object is of type Property (see GetDocumentInfo). You can set the value of the Comments property by using I.
Next, you must call the SOI method to copy a new response I from the original I. This will allow the updated response element I to be committed to the new I via the the SOI method.
Finally, you can convert the modified response I to a string through the SOI method. This modified string response will be returned in the handle method and sent to the client.
To test how the above code works in the SOI, you can deploy the SOI and enable the SOI with a map service. You can use any non-ArcObjects-based SOAP client to send a GetDocumentInfo request, and you will find the value of the Comments property in the response XML shows the custom message defined in the SOI.