PLEASE HELP! Features do not get updated in Geoprocessing Service

727
10
Jump to solution
10-11-2013 07:55 AM
ionarawilson1
Occasional Contributor III
I am at my wits end with this and it seems that ESRI does not provide much information about this. My data is in SDE. This script works in ArcMap but it does not update the features when it is run with a geoprocessing service. I don't think I can write an absolute path for the inputs as this gp will be used in a web app. Can anybody help?

# Import arcpy module import os, sys, arcpy, traceback, arcgisscripting  arcpy.env.workspace = "Database Connections\\sars.sde\\" arcpy.env.scratchWorkspace = "d:\\ArcGISData\\SARS\\Python_10April2013\\SARS.gdb"   Input_Polygons = arcpy.GetParameterAsText(0) Counties = arcpy.GetParameterAsText(1)  # create output feature for spatial join if os.path.exists("d:\\ArcGISData\\SARS\\Python_10April2013\\SARS.gdb\\StewardshipCounties"):     os.remove("d:\\ArcGISData\\SARS\\Python_10April2013\\SARS.gdb\\StewardshipCounties") outstewardshipcounties = os.path.join(arcpy.env.scratchGDB, "StewardshipCounties")   with arcpy.da.UpdateCursor(Input_Polygons, ("DateStart", "PlanID", "FFY")) as rows:               for row in rows:          if not (row[1] or "").strip(): #covers blank, one blank space, or Null             Datestarstr1 = row[0]             Datestarstr2 = str(Datestarstr1)                      yearonly = Datestarstr2[0:4]                               row[2] = yearonly              rows.updateRow(row)      arcpy.Identity_analysis(Input_Polygons, Counties, outstewardshipcounties) #run spatial join tool arcpy.CalculateField_management(Input_Polygons, "OID", '!OBJECTID!', "PYTHON_9.3")  #create dictionary  path_dict = { } rows = arcpy.SearchCursor(outstewardshipcounties) for row in rows:          keyrow =  row.OID     valrow = row.FIPS_TXT     path_dict[keyrow] = valrow  urows = arcpy.UpdateCursor(Input_Polygons) for urow in urows:      upkey = urow.OID     if upkey in path_dict:         urow.setValue("County", path_dict[upkey])         urows.updateRow(urow) del row, rows, urow, urows 
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
ionarawilson1
Occasional Contributor III
Ok, I found what the problem was. A parameter cannot have a feature class as an input (go figure!), so if you use arcpy.GetParameterAsText() and then have that parameter as a featureset (which I needed for my gp) it won't work. What I did was to create a variable for that parameter and when I run it inside ArcMap I grab the layer for that feature class (in my case the layer is referencing a feature class in a sde geodatabase). Then I publish the gp, then when I run the geoprocessing service I can grab the file directly from the connection instead of the layer. I hope it will help somebody because it took me a while to figure this out.

 Input_Polygons = "Stewardship"    with arcpy.da.UpdateCursor(Input_Polygons, ("DateStart", "PlanID", "FFY")) as rows:      for row in rows:          if not (row[1] or "").strip(): #covers blank, one blank space, or Null             Datestarstr1 = row[0]             Datestarstr2 = str(Datestarstr1)                      yearonly = Datestarstr2[0:4]                               row[2] = yearonly              rows.updateRow(row)    

View solution in original post

0 Kudos
10 Replies
T__WayneWhitley
Frequent Contributor
It seems you have been told, but you are repeating some of the same mistakes.

Think about it, how do you expect ArcGIS Server to 'know' where to look for "Database Connections"?...and 'd', what is that and why can't you use UNC pathname designations?   Database Connections is a shortcut used by the Desktop.  When the user (you) uses  Desktop, there's an interaction with your user app directory (that's the default).   Not so with Server because it really isn't necessary -- ArcGIS Server is concerned with utilizing whatever DB connections are available to publish and make available the services.  So what you can do is utilize a connection saved in a published map or access an sde connection file in an accessible location to Server and utilize your db... also, I assume you have configured your data stores?

One more thing, your script looks a little haywire, like perhaps you combined it from various sources?  Did you know (so it appears) you can just add into the updatecursor execution the calculation for OID?...rather than run a separate Calculate Field?

Hope that helps get you on track better...

Enjoy,
Wayne
0 Kudos
ionarawilson1
Occasional Contributor III
Yes, I know you talked about this before and I reread your post but it is still not clear how I make it work in this case so, based on your suggestions:

1 - How can I utilize a connection saved in a published map?

2 - How can I access an sde connection file in an accessible location to Server?

No I did not combine from various sources, but I will incorporate the calculation of the OID when I calculate the updatecursor, but mostly important I need to figure out how to make the server update the features. I appreciate your help, thanks
0 Kudos
ionarawilson1
Occasional Contributor III
I found sde connection files under

C:\Users\<username>\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog

Where do I put them now for ArcGIS Server to have access to it?
0 Kudos
T__WayneWhitley
Frequent Contributor
First I am not exactly sure what's happening on the browser end where I'm assuming your JS is sending a REST request to execute the gp task, is that a correct description of your scenario and the problem lies in the actual gp task execution itself (not the JS web map display)?

If so, your clue is that it worked in ArcMap and not otherwise calling the task.  You see?  The ArcMap doc layers themselves contain the necessary db connection parameters...so when you run the task 'outside' of the mxd, Server must 'realize' that it must get the params elsewhere, so basically you can either 'get' that in the Python script i.e. use a pathname to the sde file that Server has read privileges to.  But I think you were using layers as input (I can't remember everything from your other threads)?  If you're passing layers into the task (think that's a list by layer name, as in the TOC), then I assume you're using a 'published' map so that Server can get the layers (hence the connection params).

Hope I haven't misled you here, but that is as I understand the problem -- obviously, as I said in another thread of yours, I have some testing of my own to do.  I would pay particular attention to what Kevin Hibma has said on the matter.

Thanks,
Wayne


EDIT-
I just saw your last post, about 'where to put the .sde connection files'...  Just to be clear, I have Python scripts that are meant to execute with a map and others that only need db access.  So I have a shared mapdocs directory on the server that allows read permission for ArcServer that contains maps and also a subdirectory with some .sde file copies.  My dbs are set up with os authentication - that is for the ordinary users on my internal network, params from the file + Windows user accnt is passed.  I also have special authentication for ArcServer....so that ArcServer can access the same connection params stored in the sde file and also the windows accnt it operates under.  The db manager app does a 'handshake' with sde and windows to allow access.
0 Kudos
ionarawilson1
Occasional Contributor III
I am not even testing on the web map yet. I ran the script in ArcMap and it worked ok, then I published the geoprocessing service from the results and when I tested still in ArcMap but using the gp and grabbing the files from the connection, no errors appeared but the features do not get updated. I also tried grabbing the layers from ArcMap (the layers point to the sde files) but that caused the same issue, the gp does not give me errors but it also does not update the features.

And on the javascript side, after things work with my gp testing in ArcMap, I will be using feature services as input to the parameters of the task
0 Kudos
T__WayneWhitley
Frequent Contributor
This may or may not help - it helped me anyway, and details are important-- plus I was interested in investigating some of the Python methods just a bit further.

About what I was saying about the sde connection files and where you may place copies of them for ArcGIS Server access, I already make it common practice in scripting NOT to use the Database Connections shortcut -- ArcGIS Desktop recognizes it in your app directory when you are logged in and *everything* is running in a system-cozy manner as you, but what happens when you run a script from a place or via a user that does not have access, or in other words, things are not as convenient or familiar or friendly?

You can bypass the problem by placing connection files, etc., that are needed for a server to run your scripts in a server location....one that is of course given access to the server accts.  But I'm talking about scripts operating 'outside' an mxd.  I guess you could write all your scripts that hinge on an mxd to fetch layers to update so that in effect your sde data sources are updated.  That's fine, I'm just in the habit of when I don't need the map doc, I go straightaway to operate on the sde data source.

Ah, but the curious thing to me is ArcServer can publish map services from an mxds and I admit I've not paid too much attention to the layer properties contained there and whether the sde connection files are also needed to connect to the data source...so I did a little poking around.  See this testing via Python (in IDLE):
>>> import arcpy
>>> mxd_path = r'C:\mapdocs\MonroeCountySDE_Environmental_Layout.mxd'
>>> mxd = arcpy.mapping.MapDocument(mxd_path)
>>> mapLyrs = arcpy.mapping.ListLayers(mxd)
>>> mm = mapLyrs[1]
>>> for i, j in mm.serviceProperties.iteritems():
               print "{0}:  {1}".format(i,j)
 
               
UserName:  DBO
ServiceType:  SDE
Service:  sde:sqlserver:mc-gissql
Database:  MonroeGISData
Server:  mc-gissql
Version:  dbo.DEFAULT
AuthenticationMode:  OSA
>>>  


To explain, I gained access to one of my map docs in a ArcServer-accessible location (mapdocs), drilled to one of the map layers (the mile marker point layer, in this case the 1st layer inside an 'Overview' grouplayer), and used the serviceProperties property get (I already knew this was supported for this layer) to retrieve the stored sde connection properties.  This returns a Python dictionary...

This particular mxd/lyr object is of the 10.0 variety, so here's the relevant webhelp that lists that property in the layer class:

Layer
Resource Center » Professional Library » Geoprocessing » The ArcPy site package » Mapping module » Classes
http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//00s300000008000000


So, the critical part I want to point out here is that you can print out the sde connection properties, which if you will look will show 'OSA' for authentication --- this stands for 'operating system authentication'.  This connection is using 'direct connect' (sde:sqlserver:mc-gissql) with the username 'DBO'...this is the user set up in the database itself.  So what system user is being authenticated?  I'm using Windows so that would be the os account set up in Windows of the user passing the parameters...my db manager checks with Windows to see if the system user if valid, that's what OSA is...and of course uses the other params provided to complete the connection.

An 'extra' interesting fact is .dataSource returns the original pathname used to create the layer connection in the mxd.
>>> type(mm)
<class 'arcpy._mapping.Layer'>
>>> mm.dataSource
u'C:\\Documents and Settings\\whitley-wayne\\Desktop\\mxdMapSvcs\\MonroeGISData.sde\\MonroeGISData.DBO.BM_MileMarkers'


That's probably bad practice to leave the orig source 'pointer' pointing to a file on my PC...that was really for temp purposes only.  To 'see' if the mxd layer is indeed currently dependent on that sde connection file, the MonroeGISData.sde file was removed and the map service depending on this mxd (which no longer depends on the sde file used to initially create it when constructing the mxd) was restarted....and it operates normally to access the mm data source in my db, no sde connection file required.


Thank you,
Wayne
0 Kudos
ionarawilson1
Occasional Contributor III


Wayne, I am not sure I understand what you are saying. My script just need db access because it will be used in a javascript web app. The parameters of the task will be feature sets coming from feature services that were created using the same sde data that will be used for the geoprocessing service.
So, do I need to copy sde files to this mapdocs directory? My dbs are also set up with os authentication and the arcgis service account is a user with write/read privileges on the database. So what is exactly this special authentication for ArcServer so that it can acess the same connection params stored in the sde file and the windows account it operates under? Do you have any articles I can read about this? Have you take any classes to learn this? Thank you!
0 Kudos
T__WayneWhitley
Frequent Contributor
One more post today and I'm leaving the office...

What error messages are you getting back --- you must write that into your script, but it almost sounds to me like it's not getting launched properly i.e. the task isn't properly configured yet to read the input you intended? - I don't know without seeing more specifics.  Can you launch the task any other way...or set up a different, simpler gp task so that you can practice launching and handing off params?...if you are not getting back anything in terms of messages, what can I say?

This to me looks suspicious:
arcpy.env.workspace = "Database Connections\\sars.sde\\"
arcpy.env.scratchWorkspace = "d:\\ArcGISData\\SARS\\Python_10April2013\\SARS.gdb"

You should test UNC pathnames, for example in my 'mapdocs' example, I reference it in my scripts (because I've shared that location on the network) as:

\\mc-gisappserver\mapdocs...

As I said, my mxds are there (which are published) and I have sde connection file copies for server-launched scripts to access.

So that workspace statement would look something like:
arcpy.env.workspace = r"\\mc-gisappserver\mapdocs\somesubfolder\sars.sde"
arcpy.env.scratchWorkspace = r"\\mc-gisappserver\mapdocs\sometemp\SARS.gdb"


You don't have to make a 'mapdoc' folder - you can make whatever you like, just make sure ArcGIS Server has access.


Have a good weekend -- I'll be looking in later.  Any more web-service-related questions, I suggest you heed the advice of those on the Server forum and the nicely succinct advice of Kevin (as I also mentioned earlier) and others.


Enjoy,
Wayne
0 Kudos
ionarawilson1
Occasional Contributor III
I get no errors at all, but I look at the feature and it has not been updated. Before when I had the first parameter value set as just:

Input_Polygons = "Stewardship"

and I had the toolbox parameter called Stewardship and the type was featureset and things worked great. I tested the gp in my web app and it was working great. However when I added the counties, I started getting error messages when trying to publish as a gp and decided to go back to using InputPolygons = arcpy.GetParameterAsText(0) and then added
Counties = arcpy.GetParameterAsText(1). The errors stopped when I run the gp but the features do not get updated.

So when you say, you have connection files in  your arcgis server, how do you move them there? It is because I do not have direct access to the server through the windows explorer or arcCatalog so I am not sure how to copy files there. In your case, you copied the files to

r"\\mc-gisappserver\


In my case, I would need to find the server folder trhough ArcCatalog (which I don't have access) and then copy the files to a subfolder there? How do I get access to this server folder that in your case is mc-gisappserver, but that in my case is probably different? The arcgis server is not installed in my machine. I can connect as a user and a publisher but I can't copy files directly. How do you do that?


Also, I read the other post by Kevin but I do not think applies to my case.


Thank you and have a great weekend.
0 Kudos