R-ArcGIS / r-bridge

Bridge library to connect ArcGIS and R, including arcgisbinding R library.
Apache License 2.0
117 stars 26 forks source link

arc.portal_connect() or arc.check_portal() results in an "attempt to set an attribute on NULL" error #88

Open erikdesilva-nps opened 7 months ago

erikdesilva-nps commented 7 months ago

Describe the bug

Attempting to use arc.portal_connect() or arc.check_portal() results in an "attempt to set an attribute on NULL" error.

To Reproduce

arc.portal_connect(  
     Sys.getenv("PORTAL_URL"),  
     Sys.getenv("PORTAL_USER"),  
     Sys.getenv("PORTAL_SECRET")
)

Screenshots

image

arcgisbinding info (please complete the following information):

Additional context

JosiahParry commented 7 months ago

Thanks for sharing this. The screenshot looks like xml. What do you get when you run this from an R console?

Also, what is your objective? Perhaps our newer packages might be able to assist.

erikdesilva-nps commented 7 months ago

Thanks for your response. As requested, here's the output from an attempt to run arc.check_portal() from the terminal:

> library(arcgisbinding)
> arc.check_portal()
Error in class(info) <- c("arc.portalinfo", class(info)) :
  attempt to set an attribute on NULL

As well as arc.portal_connect():

> arc.portal_connect(
+   Sys.getenv("PORTAL_URL"),
+   Sys.getenv("PORTAL_USER"),
+   Sys.getenv("PORTAL_SECRET")
+ )
Error in .call_proxy("arc_portal", url, user, password, token) :
  unknown error

The goal is to have the web tool grab the data out of ArcGIS Online, perform some data munging, then return a Word document (.docx) to the user. It works fine when run on my local machine, but something in the server implementation is giving me trouble. I'm all ears if there's a newer, more suitable package -- the only functions I'm using from arcgisbinding are arc.portal_connect() and arc.select().

JosiahParry commented 7 months ago

I hope you don't mind me being a little bit pedantic! Do you mind walking me through what you're trying to accomplish and how you're doing it. This will help give me a better picture so I can either try and replicate it or try and figure out what might be going wrong.

So far, from what I can piece together, you have an R-based web service that is using R & arcgisbinding. Inside of the tool_exec() function as part of the web tool, you're using arc.portal_connect() to sign into a web portal and read some data and nothing else with the tool.

Right now you're getting an error when running arc.check_portal(). First off, can you let us know what version of arcgisbinding you're using?

Secondly, it may be worth trying {arcgislayers} which is going to be published in the next month or so.

https://r.esri.com/r-bridge-site/location-services/connecting-to-a-portal.html

erikdesilva-nps commented 7 months ago

No worries! Apologies for not being clearer. You are correct. I've written a geoprocessing tool using R which:

  1. Logs in to ArcGIS Online with arc.portal_connect()
  2. Grabs some data from a hosted feature service in ArcGIS Online using arc.select(), pointed at the FeatureServer layer urls
  3. Summarizes the data using dplyr
  4. Generates some native Word tables using officer and flextable
  5. Generates a couple figures using ggplot2
  6. Inserts the generated content into a template .docx file using officer
  7. Emails the resulting .docx file to a user-supplied list of email addresses via sendmailR

Right now the tool will run on my local machine with ArcGIS Pro 3.1.2 installed. The issue arises once the tool is published to our ArcGIS Server instance and ran from there.

Here's the output from sessionInfo() with only the arcgisbinding package loaded. arcgisbinding version is 1.0.1.306.

> library(arcgisbinding)
*** Please call arc.check_product() to define a desktop license.
> sessionInfo()
R version 4.2.3 (2023-03-15 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows Server x64 (build 14393)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] arcgisbinding_1.0.1.306

loaded via a namespace (and not attached):
[1] compiler_4.2.3

Finally, here's an attempt to run arc.check_portal() from a brand new session with no other packages loaded:


R version 4.2.3 (2023-03-15 ucrt) -- "Shortstop Beagle"
Copyright (C) 2023 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> library(arcgisbinding)
*** Please call arc.check_product() to define a desktop license.
> arc.check_portal()
Error in class(info) <- c("arc.portalinfo", class(info)) :
  attempt to set an attribute on NULL

Same thing, but for arc.portal_connect()

R version 4.2.3 (2023-03-15 ucrt) -- "Shortstop Beagle"
Copyright (C) 2023 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

[...]

> library(arcgisbinding)
*** Please call arc.check_product() to define a desktop license.
> arc.portal_connect(url="https://www.arcgis.com", user="my_username", password="my_password")
Error in .call_proxy("arc_portal", url, user, password, token) :
  unknown error

Thanks for the info about arcgislayers! I may put this project on pause and check in during March if this doesn't resolve easily.

JosiahParry commented 7 months ago

Thank you! My guess is that this may have to do with the fact that it is expecting a local installation of ArcGIS Pro. I, however, do not know the internals of the C/++ so I'll see if I can get an answer from our dev.

However, if you want to try using arcgislayers, here's how you would replicate your workflow:

# pak::pak("r-arcgis/arcgislayers")
library(arcgisutils)
library(arcgislayers)

# these are all the default arguments
token <- auth_user(
  username = Sys.getenv("ARCGIS_USER"),
  password = Sys.getenv("ARCGIS_PASSWORD"),
  host = arc_host() # defaults to arcgis.com
)

# if you're using a client id & client secret:
token <- auth_client(
  client = Sys.getenv("ARCGIS_CLIENT"),
  secret = Sys.getenv("ARCGIS_SECRET"),
  host = arc_host()
)

set_auth_token(token)

furl <-
  "https://services3.arcgis.com/ZvidGQkLaDJxRSJ2/arcgis/rest/services/PLACES_LocalData_for_BetterHealth/FeatureServer/0"

flayer <- arc_open(furl)
my_sf_obj <- arc_select(flayer)
scw commented 7 months ago

@erikdesilva-nps for the standalone calls you ran, would you be able to run arc.check_product() and see if it changes the result?

The setup for server is somewhat complicated, particularly at the 10.x releases. Services can be bound to the 10.x based runtime, or the Pro based runtime (this is simplified at Server 11.0+, there is only the Pro based runtime). So what may be happening is that your service is being initialized within the 10.x runtime, and in that case it will pick up the 10.x context.

Overall, I think working with arcgislayers may be better matched to what you're trying to accomplish, but wanted to chime in with respect to the Server aspect.

erikdesilva-nps commented 1 month ago

Hey all, following up on this.

I switched to the arcgisutils / arcgislayers setup outlined by Josiah above, and everything worked great... Until R updated to 4.4.1. Now I'm able to run the code fine in a terminal session, but running it from its geoprocessing tool endpoint yields this error:

esriJobMessageTypeError: Error in askYesNo : Unrecognized response "tryCatch(withRestarts(withCallingHandlers(eval(.arc_cmd2),error=function(e)invokeRestart('big.bada.boom', e, sys.call(sys.parent()-2L)),warning=function(w){.Call('arc_warning', conditionMessage(w), PACKAGE='rarcproxy_pro'); invokeRestart('muffleWarning')}),big.bada.boom=function(e, calls){trace.back <- lapply(calls, deparse)"

We've updated to ArcGIS Server 11.2 since I've started this project, if that helps. I can also start a new issue if it would be easier for you folks to keep track of.

JosiahParry commented 1 month ago

"Big bada boom" hah seems like an appropriate error message.

Can you please share what code you are running?

erikdesilva-nps commented 1 month ago

Big bada boom indeed! Here's a small reproducible snippet which triggers the error, with the caveat that it has to be run via a geoprocessing tool:

tool_exec <-
  function (in_params, out_params = list()) {

    old_path <- Sys.getenv("PATH")
    if (!grepl("C:\\Program Files\\R\\R-4.4.1\\bin\\x64", old_path, fixed=TRUE)){
      Sys.setenv(PATH=paste("C:\\Program Files\\R\\R-4.4.1\\bin\\x64", old_path, sep=";"))
    }
    readRenviron(file.path("C:\\GeodatabaseScripts", ".Renviron"))

    library(arcgisutils)
    library(arcgislayers)
    sapply(c(
      'ggpubr',
      'fs',
      'dplyr',
      'tidyr',
      'ggplot2',
      'gridExtra',
      'officer',
      'flextable',
      'colorspace',
      'showtext',
      'sendmailR'
    ), function(p) {
      if (!requireNamespace(p, quietly = TRUE)) {
        install.packages(p, quiet = TRUE, repos = "http://cran.rstudio.com/")
      }
      require(p, character.only = TRUE, quietly = TRUE)
    })
    message("Libraries loaded.")

    token <- auth_client(
      client = Sys.getenv("VRP_CLIENT"),
      secret = Sys.getenv("VRP_SECRET"),
      host = arc_host()
    )
    set_arc_token(token)
    return(TRUE)
}

I've been able to reproduce the error on my desktop running ArcGIS Pro 3.3.1 / R 4.4.1. On my desktop I was able to fix it by commenting out lines 5 - 8 (setting the PATH variable), but on the server that results in arcgislayers not being able to find the stats.dll file from base R. It feels like something's a bit hinkey in our R install on the server...