Sometimes you might want fine-grained control over your service properties when you initially publish a service. You can achieve this by listing service parameters in a text file using JavaScript Object Notation (JSON). You then call the createService method in the ArcGIS REST API and pass in the JSON that you have read from the file.
In the case of a map service, you must specify a map service definition (MSD) file in your JSON. This file synthesizes information from your ArcMap document (MXD) in a format that can be understood and drawn by ArcGIS Server. You must use the arcpy.mapping module to analyze your map and create the MSD before you can go ahead with creating the service. This part requires a machine licensed for ArcGIS Desktop. Other service types do not require you to use arcpy.mapping or create an MSD.
Here's an example of how your JSON file might look. Refer to the ArcGIS REST API reference for detailed examples of how to create the JSON file for different service types.
{ "serviceName": "Beirut", "type": "MapServer", "description": "Service showing Beirut parcels and streets.", "capabilities": "Map,Query,Data", "clusterName": "default", "minInstancesPerNode": 1, "maxInstancesPerNode": 3, "instancesPerContainer": 1, "maxWaitTime": 60, "maxStartupTime": 300, "maxIdleTime": 1800, "maxUsageTime": 600, "loadBalancing": "ROUND_ROBIN", "isolationLevel": "HIGH", "configuredState": "STARTED", "recycleInterval": 24, "recycleStartTime": "00:00", "keepAliveInterval": 1800, "private": false, "isDefault": false, "properties": { "maxBufferCount": "100", "maxImageHeight": "2048", "maxRecordCount": "1000", "filePath": "c:\\data\\Beirut\\Beirut_Parcels.msd", "maxImageWidth": "2048", "enableDynamicLayers": "false", "cacheOnDemand": "false", "dynamicDataWorkspaces": "", "useLocalCacheDir": "true", "outputDir": "c:\\arcgisserver\\directories\\arcgisoutput", "virtualOutputDir": "/rest/directories/arcgisoutput", "supportedImageReturnTypes": "URL", "isCached": "false", "ignoreCache": "false", "clientCachingAllowed": "true", "cacheDir": "" }, "extensions": [], "datasets": []}
The code below shows how you might reference the content of this JSON file in a Python script when publishing a service.
# Demonstrates how to publish a service from a JSON definition file
# An MSD file is required, which is made from the MXD in this script
# For Http calls
import httplib, urllib, json, arcpy, os
# For system tools
import sys
# For reading passwords without echoing
import getpass
# Defines the entry point into the script
def main(argv=None):
# Print some info
print
print "This tool is a sample script that publishes a service using an MXD and JSON definiton."
print
# Ask for admin/publisher user name and password
username = raw_input("Enter user name: ")
password = getpass.getpass("Enter password: ")
# Ask for other necessary information
serverName = raw_input("Enter Server name: ")
serverPort = 6080
mxdPath = raw_input("Enter the path to the MXD: ")
msdPath = raw_input("Enter the desired path for the MSD: ")
jsonPath = raw_input("Enter the path to the JSON file: ")
# Analyze MXD and create MSD file
if not os.path.isfile(mxdPath):
return
if mxdPath.endswith('.mxd'):
mapErrors = analyzeMap(mxdPath)
if len(mapErrors) > 0:
print "Fix map errors before converting to mxd"
return
mxd = arcpy.mapping.MapDocument(mxdPath)
convertMap(mxd, msdPath);
del mxd
else:
print "Invalid file type submitted"
return
# Get a token
token = getToken(username, password, serverName, serverPort)
if token == "":
print "Could not generate a token with the username and password provided."
return
# Read the JSON file for the service
serviceJSON = open(jsonPath).read()
# Construct URL to create a service
# If publishing to a folder, invoke createService on the folder URL
createServiceURL = "/arcgis/admin/services/createService"
# This request needs the token, the JSON defining the service properties,
# and the response format
params = urllib.urlencode({'token': token, 'service':serviceJSON, 'f': 'json'})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
# Connect to URL and post parameters
httpConn = httplib.HTTPConnection(serverName, serverPort)
httpConn.request("POST", createServiceURL, params, headers)
# Read response
response = httpConn.getresponse()
if (response.status != 200):
httpConn.close()
print "Error while creating the service."
return
else:
data = response.read()
httpConn.close()
# Check that data returned is not an error object
if not assertJsonSuccess(data):
print "Error returned by operation. " + data
else:
print "Operation completed successfully!"
return
# A function to analyze a map document
def analyzeMap(mapPath):
mxd = arcpy.mapping.MapDocument(mapPath)
analysis = arcpy.mapping.AnalyzeForMSD(mxd)
vars = analysis['errors']
for ((message, code), layerlist) in vars.iteritems():
print "Errors: "
print message, " (CODE %i)" % code
print " applies to the following layers:",
for layer in layerlist:
print layer.name,
print
del mxd
return analysis['errors']
# A function to convert a map document to a map service definition (MSD)
def convertMap(mxd, msd):
arcpy.mapping.ConvertToMSD(mxd, msd, "USE_ACTIVE_VIEW", "NORMAL", "NORMAL")
del mxd, msd
# A function to generate a token given username, password and the adminURL.
def getToken(username, password, serverName, serverPort):
# Token URL is typically http://server[:port]/arcgis/admin/generateToken
tokenURL = "/arcgis/admin/generateToken"
# URL-encode the token parameters
params = urllib.urlencode({'username': username, 'password': password, 'client': 'requestip', 'f': 'json'})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
# Connect to URL and post parameters
httpConn = httplib.HTTPConnection(serverName, serverPort)
httpConn.request("POST", tokenURL, params, headers)
# Read response
response = httpConn.getresponse()
if (response.status != 200):
httpConn.close()
print "Error while fetching tokens from admin URL. Please check the URL and try again."
return
else:
data = response.read()
httpConn.close()
# Check that data returned is not an error object
if not assertJsonSuccess(data):
return
# Extract the token from it
token = json.loads(data)
return token['token']
# A function that checks that the input JSON object
# is not an error object.
def assertJsonSuccess(data):
obj = json.loads(data)
if 'status' in obj and obj['status'] == "error":
print "Error: JSON object returns an error. " + str(obj)
return False
else:
return True
# Script start
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))