Getting a REST model to "draw" its fields down from the service?

  • 1
  • Question
  • Updated 3 months ago
  • Answered
This is something that I am sure is possible, but I can't quite seem to get working.

tl;dr:

I have a RESTful webservice set up (and all that works, Querying/Inserting etc.) but in order to do so, I had to "add" all the fields to the REST model in Skuid myself.

This was ok for the proof of concept I was delivering, but now I need to take this to the next level, and a requirement is that should the responses definition change on the service, Skuid needs to "easily" take these new fields into account.

It sounds daft, but I am sure at some point in the past, I used the Skuid REST Model builder to somehow "unpick" the service results and create a bunch of fields for me, can anyone prompt me as to how this is done?

Loads more detail:

So it's actually a Salesforce REST webservice I am contacting. 

And lets say it has an inner class return type like so:




I can then define my REST data source, similar to so:



And this all "works" for GETting and POSTing data to and from my webservice (I know there is no Insert/Update method in that screenshot! They are dummies). But like I said, I had to create the fields "billNo" and "billAmt" on the model myself.

If I look at the fields list (prior to creating them by hand) I literally get blank:



and this makes me wonder, because if I "break" my REST model (change the service call or settings etc) I do get this:



So it looks like the field list is trying to load some fields, and not getting any.

My GET method does return void because I put my payload in the response body, as serialised JSON... but even if I give it a return type and throw back one of my objects, I cannot seem to get Skuid to deduce the fields in the response.

Things I don't know about - do I need to define a POST (be it a Query or Insert) method on the Skuid model? Do I need to return from my GET, am I making my responseBody wrong? (it's totally standard RESTful JSON) do I need to tell Skuid how to interpret the response...? is it more complicated than that even?!! 

I am aware of this "Path to Contents" field.. but when I pop that out - there are no fields to select, because - likewise - I don't think Skuid is working out the response it'll be getting from this service.

Any input very welcome. I consider myself pretty well Skuid and programming experienced, so feel free to go hard on the terminology and concepts :D
Photo of srlawr

srlawr

  • 592 Points 500 badge 2x thumb

Posted 4 months ago

  • 1
Photo of Zach McElrath

Zach McElrath, Employee

  • 52,236 Points 50k badge 2x thumb
What is your Apex REST endpoint actually returning? Can you post at least the method signature for your Apex @Get method ? Is it returning a List<ReturnObject> , or a single ReturnObject ? Or are you serializing to JSON (I wouldn't)? Does your "Path to Contents" currently have a value? 
Photo of srlawr

srlawr

  • 592 Points 500 badge 2x thumb
Hi Zach. The Apex REST GET endpoint currently returns void, and the method adds a serialisation of a List<ReturnObject> to the response body.

Would be interested to hear why that isn't recommended! Equally, I am 100% happy to do whatever I need to do in this method to make this work.

I did try changing return type to List<ReturnObject> and indeed just a single ReturnObject and then actually returning stuff from the GET method, but this didn't get me any closer to seeing my fields within the Skuid page builder.

As a picture is worth a thousand words, here is a cut down of the method as it stands (imagine that at line 51 going forward, I actually do a bunch of wrangling):




It's slightly tricky because technically the GET doesn't make any sense "off the bat" - as the page and webservice needs context before an actual record could be returned, but I am also perfectly happy to work around this, and just return an initialised (but perhaps empty/irrelevant) instance of the ReturnObject.

It would really have to be a list of them though, with a single element? But again - happy to re-butcher other parts of my work to get this trick sorted!


Is the return type of the GET the key here? 

(can I also point out I do not produce code with methods called retrieveAndReturn and objects named ReturnObject in my day to day life :D :D I am obfuscating for the sake of my projects privacy!!)
Photo of Zach McElrath

Zach McElrath, Employee

  • 52,236 Points 50k badge 2x thumb
Haha, I always pre-obfuscate all of my code so that even i can't understand it :)

Would be interested to dig into what you mean by 'it doesn't make any sense off the bat' ... 

But basically the approach you described would be correct --- define a wrapper class, like you've done, and then give it an optional "error" property, like this:

public class ReturnObj {
   public String billNo, billAmt, error;
}

@Get
public static List<ReturnObj> GetReturnObject() {


     ReturnObj obj = new ReturnObj();

     try {
          ...
         obj.billNo = "123";
         obj.billAmt = "123.45";
     } catch (Exception ex) {
          obj.error = ex.getMessage();
          RestContext.response.statusCode = 500;
     }

     return new List<ReturnObj>{obj};


The reason I'd go down this approach is that you take advantage of native serialization, rather than you having to do it yourself, and less code.

The return type of the GET response is important. If it's overly-serialized, Skuid will not be able to "draw" the fields out by auto-parsing the GET response.
Photo of srlawr

srlawr

  • 592 Points 500 badge 2x thumb
Thank you Zach, for all your help! The reason calling the GET "off the bat" doesn't make much sense is because this page/exchange is made up of a whole bunch of calls/data, in which the data retrieved by the GET doesn't exist until the user has done a bunch of stuff on page and made a POST to that service end point, until then there isn't any "bill object" to return. Nothing is actually even persisted by this exchange, so initialising the page and calling the GET will just turn up nothing. I hope perhaps that makes some sense, it's complicated (of course!).

But to the problem! It appears it is solved! I don't know if this is working-as-designed, but you don't get the Data Source Options on the model if the REST Model is defined as Read/Write. Only if it is "Read Only"

Having applied your advice above, and then out of clicking-frustration, I changed the REST model to be read only, and suddenly the Data Source fields appear at the model level (and obviously the ability to define other methods on this model disappear, as they are all Write based methodologies).




If I stick my service resource location in there, and leave it as GET - the field list suddenly shoots out all the fields in my return type - as you expected!

If I flip this back to "Model Behavior = Read/Write" then the two inputs above disappear, and I am returned to adding methods to the model myself.





and



right?

However, all the fields remain - which kinda makes sense, once they are in the XML I'd be surprised if that would make a bunch of destructive changes.

Spurred on by this sudden success I have been back round and round the houses trying to get the Read/Write behavior to pull the fields out again, but I simply cannot configure a Method that does it.

I can get it back every time when I flip it to Read mode.

I wonder then if you can confirm - that's how it's supposed to work? I can't think why it wouldn't want to do the field detection if you wanted a Read/Write REST model, it could still just use the Query method - and it's really just a convenience that it does this, you can still manually add and remove fields?

If this isn't what we'd expect, I'm using Skuid v12.0.1 and I'm happy to document/recreate this in as much detail as might be helpful :)


(Edited)
Photo of Zach McElrath

Zach McElrath, Employee

  • 52,236 Points 50k badge 2x thumb
Hmm, that's not what I'd expect --- this should work either way, with Read-Only or Read-Write. It might be an issue with Skuid trying to be smart and copy your Service URL, Verb, Path to Contents, etc. over from the top-level Model properties down into the Query method, which it does when you switch from Read-Only to Read-Write. It might be instructive to switch to Read-Write, then see what's in the XML for the Model's Methods. (Go to "View/Page XML" and then look for the <methods> node within your Model's XML.

But if that's not working, it might be a bug.
Photo of srlawr

srlawr

  • 592 Points 500 badge 2x thumb
Hi again Zach, thanks again for your help! It is now working, and I can make it consistently work with Read and Read/Write REST models; over and over. however I think really deep down there is something of a "bug" somewhere, because if I fiddle with the Methods and Settings of a REST model enough, I can get it to eventually "stop" successfully interpreting the fields at some point or other - I'm afraid I just can't put my finger on what point exactly this happens.

Of course, so long as at any point (I would suggest the earlier the better!) you click on the "fields" menu item, once it has them down, they stay down! So I am definitely not going to worry about this any longer. It is, in fact, really quite clever to be honest - so I'm just glad it works at all!

cheers.
Photo of Zach McElrath

Zach McElrath, Employee

  • 52,236 Points 50k badge 2x thumb
Good to know, will still see if we can replicate the behavior where the field auto-discovery stops working.