Editor writing to JSON REST API?
Editor writing to JSON REST API?
I have existing REST APIs which take JSON objects, and they worked great for getting data for display DataTables; I was hoping insert/update/delete through Editor would be just as easy, but I'm not finding quite what I was hoping for.
I see instructions here for making Editor do (for example) a POST to /api/users
to add a new user, PUT or POST to /api/users/666
to edit user 666, and DELETE to /api/users/666
to delete user 666 (and using separate methods like that is working for me), and I see instructions here for converting the request to JSON (which is also working for me), but... my problem is that the structure of the data is not quite what my existing APIs want. For example, if my User object looks like this:
{
"id": 666,
"name": "Necrobutcher",
"jobTitle": "Bassist"
}
then a POST to /api/users
expects one of those (minus the "id" attribute), and a PUT or POST to /api/users/666
expects one of those with the updated values (and, again, it's fine if the "id" attribute is absent, as I get it from the URL anyway). Instead, adding a new user sends this to /api/users
:
{
"action": "create",
"data": {
"0": {
"name": "Euronymous",
"jobTitle": "Guitarist"
}
}
}
and editing an existing user sends this to /api/users/666
:
{
"action": "edit",
"data": {
"666": {
"name": "Necrobutcher",
"jobTitle": "Survivor"
}
}
}
My options seem to be A) fiddle with the structure in JavaScript to match what my existing APIs expect, or B) add APIs on the server side to support the structure Editor wants.
One disadvantage of A is that I'm a Java guy, not so much a JavaScript guy, so the less JavaScript I write, the better. Copying the approach from here, it looks like I can extract the first value of the data
hash and pass that as the created/edited object... and handle success & failure, as in the example... but that seems fragile, and I'm not sure I have the JavaScript chops to make that reusable (it'll need to be slightly different in a bunch of different pages).
The disadvantage of B (which, unlike A, I know I can do) is that I don't want to write new server code every time I add a new client! And if I'm doing that, the client-side code gets a lot simpler if I just do things the way Editor wants, and don't make it RESTful, instead having one endpoint per DataTable (rather than one for insert, one for edit, one for delete).
Thoughts? Is there an existing library which already does what I want? I know I'm not the first person trying to do this sort of thing!
This question has an accepted answers - jump to answer
Answers
Biting the bullet and just doing it on the server really isn't too bad; I got inserts working in under an hour (probably 20 minutes of which was spent shaking my fist and shouting "why must I mess up my beautiful API?"), and updates & deletes will take less than that. Maybe I'll add my code here afterward.
The
ajax
option provides the ability to send the different create, edit and remove commands to different URLs, along with different verbs (needed by REST) - example here.It also allows you to include the row id in the url - e.g.
Very likely you will want to use
preSubmit
to modify the data that Editor sends to the server since most REST APIs don't support multi-row editing (so there is no need to encapsulate the data in thedata
object).Allan
Yes, that's working for me (that's the first link in my question, and the row ID is included in the URL in my "editing an existing user" code snippet above); the issue is that the structure of the data being sent to the server isn't what the existing server-side API expects.
It looks like using
preSubmit
would let me extract the element I want to send... but then the problem is that Editor wants to receive the new/updated object wrapped in other stuff too (and I think it doesn't like that I'm returning HTTP 400s instead of 200s on errors), so I found it easier to just accommodate Editor on the server side.(In a minute I'll post the server-side changes I made, in case anyone else might find them useful.)
Suppose you have an existing RESTful API using Spring, and the Java code for your clean, beautiful API looks like this:
(Note that, in that example,
YourThing
usesint
IDs, but it could useString
or whatever instead.)Because you might have many classes which have their own controllers which will be edited through Editor, you're going to add a couple of general-purpose classes to handle communication with Editor.
And this class:
Then, back in your controller, add this method. Note that you need to make sure the request mapping won't collide with one of your objects' IDs; if that's a concern, see later.
Or, if you don't want to mess with your controller (because you don't want the editor URL to collide with one of your YourThing URLs), you could add a separate controller,
@Autowire
yourYourThingController
, and choose a request mapping which isn't under/api/yourThings
.Back on the JavaScript side, convert to JSON on the way in:
Hopefully that saves someone some time!
Amazing - thank you for writing that up!
Allan
Chrome's developer tools shows that Editor's ajax call always converts any contenttype to "www-form-urlencoded" when sending a request to the server
no matter what is manually specified in Options 'contentType' and "dataType".
On the other hand, FormHttpMessageConverter in RestController has no ability to understand and map a "complicated-structure" request of contenttype "www-form-urlencoded" to a MultiValueMap object.
This is a key problem in Editor's ajax call to Java server side.
Hi Folks,
Has anyone used this for C# ?
Being an Oracle developer with little C# skills I need to try and mimic this solution.
I think it's more the bit about adding the getters and setters that's confusing me.
Any help would be much appreciated in trying to get a handle on the request and response objects.
Cheers