I find that after upgrading to libraries to use 2.4.2 jackson-datatype-hibernate4 that most of the classes are being proxied correctly. But I also find that below classes show content as null in rendered json even though there is data.
UserPost
GroupPost
UserGroupPost
If I use projections then it is rendered / if I disable Hibernate proxies and enable JsonIgnoreProperties on "hibernateLazyInitializer" and "handler" , then also it is rendered.
Is their a possibility that Entities whose name is ending with Post are causing some kind of mixup ? I tested about 50 models and only find this happening with these Entities and are configured exactly like others and therefore am thinking in this direction ..
So when I go to /userGroupComments/12/userGroupPost I get below output, where UserGroupPost -> 1.* -> UserGroupComment
using Spring Data Rest , JPA latest builds(1.8.0.M1)
OUTPUT:
{
"content" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/app/userGroupPosts/4"
},
"userGroupComments" : {
"href" : "http://localhost:8080/app/userGroupPosts/4/userGroupComments"
},
"userPost" : {
"href" : "http://localhost:8080/app/userGroupPosts/4/userPost"
}
}
}
Links are correctly getting rendered but not the content. Entities are annotated with #AccessType(Type.PROPERTY) from org.springframework.data.annotation.AccessType
Related
The background is I have a custom JSON based language.
Consider the following
In file 1, I have the following:
[
{
"name" : "abcde",
"source" : "source::abcde",
// other attributes
},
{
"name" : "qwerty",
"source" : "source::qwerty"
// other attributes
},
]
In file 2, I have the following:
abcde.json
{
"name" : "abcde"
// properties related to it
}
querty.json
{
"name" : "querty"
// properties related to it
}
Now, I want to build an extension/ grammar such that when a visitor uses Ctrl + click on source::abcde, it takes them to abcde.json.
I am wondering how to achieve through a VS code extension. I dont have a lot of expertise in this area.
I took a look into https://marketplace.visualstudio.com/ , could not find one directly. I have 10000+ such definitions, it is becoming very hard to maintain and update these.
Any help on how to achieve this? or some pointing blogs would be really helpful
We currently have 4 content types that might be included in a delivery. In about 8-12 months we will probably have another 2-4 content types. I'm working on a public REST api now and wondering whether I can write the api in such a way that the future additions won't require a version bump?
Currently we are thinking a delivery would return a json result kind of like this:
{
"dateDelivered": "2016-01-01",
"clientId": "000001",
"contentCounts" : {
"total" : 100,
"articles": 75,
"slideshows": 25
... // other content types as we add them
}
"content" : {
"articles" : "http://api.example.com/v0/deliveries/1234/content/articles",
"slideshows" : "http://api.example.com/v0/deliveries/1234/content/slideshows",
... // other content types as we add them
}
}
That defines contentCounts and content as objects with an optional property for each available content type. I suppose I could define that as an array of objects for each content type, but I don't see how that would really change anything.
Is there any reason it be a breaking change if in the future the result object looked more like this:
{
"dateDelivered": "2016-01-01",
"clientId": "000001",
"contentCounts" : {
"total" : 150,
"articles": 75,
"slideshows": 25,
"events": 25,
"videos": 25
}
"content" : {
"articles" : "http://api.example.com/v0/deliveries/1234/content/articles",
"slideshows" : "http://api.example.com/v0/deliveries/1234/content/slideshows",
"events" : "http://api.example.com/v0/deliveries/1234/content/events",
"videos" : "http://api.example.com/v0/deliveries/1234/content/videos"
}
}
Breaking change is a relative notion.
It is breaking the client code that does not account for those changes.
In your case, if a client of your REST API has hardcoded the content types, then he will need to change his code to account for new content types.
In that sense, his code is broken because it does not handle all of it.
In another sense, his code is not broken because as long as you do not remove content types, his code will continue to work for the content types it supports.
If the client code is smart enough to iterate through properties and be flexible about the changes, it is fine.
In any case, if you plan on changing the model, you should mention it.
Whether it is adding, removing or renaming those content types, if the client knows it, he can write a client that will successfully use your REST API. In that case, NO, it would not be a breaking change because is has a dynamic structure (content types can vary) but in a structured way.
I am attempting to use the Confluence REST API to correct the tree structure of pages on a Confluence site. I can do this manually, however there are quite a few pages and I already have the tree structure in another XML file.
Currently I am able to upload pages and images using the confluence REST API. Definitions are located here.
I have attempted to use the /rest/api/content/{id} PUT command. This requires the content to be in the body of the request. Attaching the content I had received from a previous GET request I find I have to update the version count.
The above all works. Adding to the ancestor list however doesn't seem to. If I add the parent page to the list of ancestors I get formatting errors reported back.
Added to this if I manually attach the page to another page and request its contents I find that the parent appears twice in the ancestor list. Also the history count does not increase.
The resulting JSON returned from a GET request for the page:
http://someconfluencesite.com/rest/api/content/10031361?expand=ancestors (200)
{
"id" : "10031361",
"type" : "page",
"title" : "Automatic Action Usage Updates",
"ancestors" : [{
"id" : "10031327",
"type" : "page",
"title" : "Action Lists"
}, {
"id" : "10031327",
"type" : "page",
"title" : "Action Lists"
}, {
"id" : "10031328",
"type" : "page",
"title" : "Actions Tab"
}, {
"id" : "10031327",
"type" : "page",
"title" : "Action Lists"
}, {
"id" : "10031327",
"type" : "page",
"title" : "Action Lists"
}, {
"id" : "10031328",
"type" : "page",
"title" : "Actions Tab"
}
]
}
The tree this is for looks like the following:
Space
Action Lists
Actions Tab
Automatic Action Usage Updates
This leads me to believe I am using the wrong command.
I have attempted to contact Confluence support however their authorization emails are not arriving in my inbox. So I have come here :)
So my question is what is the REST call for creating a page tree in confluence? After that, what is the format of the request body?
Edit:
The following PUT request gets a successful return code. Yet the returned object does not have the ancestor attached (not unusual as in all GET requests you have to expand to get it). The version number does not update. The two pages are not hooked to each other either.
{
"id":"10552520",
"type":"page",
"title":"Correct Page Title",
"ancestor":[
{
"id":"10552522",
"type":"page"
}],
"version":
{
"number":"2"
}
}
The nice thing the above does though is delete all the contents of the page.
The following POST call results in the page being created but having no ancestors. The ancestor exists with the id supplied. Strangely this also is created without any content in the page.
{
"type":"page",
"title":"Correct Title",
"space":{"key":"SpaceKey"},
"ancestor":[{"id":"10553655","type":"page"}],
"body":{"storage":{"value":"<p>New Page </p>","representation":"storage"}}
}
Putting the above into the REST API browser also results in the children not being attached to the parent.
So it appears the answer to my question is in the question itself.
The JSON needed to have "ancestors" not "ancestor" as the array name for the ancestors array. Once this was changed it all works for a POST request.
So if your reading this and having similar issues make sure that all the element names in the JSON your passing are correct. If they aren't, they simply are ignored.
{
"id":"10552520",
"type":"page",
"title":"Correct Page Title",
"ancestors":[
{
"id":"10552522",
"type":"page"
}
],
"version":
{
"number":"2"
}
}
It's "ancestors", not "ancestor".
To move an existing page first get it's version, space, etc.
Then call PUT with version + 1, space, ancestors, title.
pageaschild = { "type":"page",
"title":name,
"space":{"key":space},
"ancestors":[{"id":ancestorid,"type":"page"}],
"version":{"number":version}};
$.ajax({type:'PUT', url:baseURL + pageId, contentType:"application/json;charset=utf-8", data:JSON.stringify(pageaschild)});
Take the following URI's as an example:
/tracks
/tracks/:id
/playlists
/playlists/:id
/playlists/:id/tracks
I have a question about the last URI (/playlists/:id/tracks). How do I add extra information/context to the track objects in relation to it's parent playlist?
Examples of context:
Added time of the track to the playlist
Play count of the track within the playlist
Likes per track within the playlist
All tracks have a created timestamp, play count and likes on a global scale. So my question is how would this information be added to the response of the endpoint.
I've come up with following for now:
{
"title" : "harder better faster stronger",
"artist" : "daft punk",
"likes" : 234252,
"created_at" : "2012-10-03 09:57:04"
"play_count" : 1203200035,
"relation_to_parent": {
"likes" : 5,
"created_at" : "2014-11-07 19:21:64",
"play_count" : 20
}
}
I've added a field called relation_to_parent which adds some context to the relation between the child and it's parent. I'm not sure though if this is a good way to do it. Hope to hear some other solutions.
By 1:n relations you can define a subresource. By n:m relations it is better to define a separate relationship resource. Note that these are just best practices, not standards.
Be aware that you can add links pointing to a different resource. According to the HATEOAS constraint you have to create hyperlinks if you want to expose an operation (for example getting another resource).
I don't think there is a 'one true way' to do this. Personally, I dislike adding the extra information like that, since you are giving a resource-plus, when you are looking for a resource. In any case, are 'likes' and 'created_at' and 'play_count' actually part of the relation to the parent, aren't they part of the track itself?
The two paths I usually see for this are:
/playlist/:id/tracks - returns a list of IDs (or URLs) for actual tracks, which you then fetch with /tracks/:track
/playlist/:id/tracks - returns the actual tracks, as if you did both steps in 1 above.
As for additional information, if it is not part of the tracks, you might do it as (any of these is valid):
info as part of the track, so /tracks/:track always returns the 'play_count' and 'likes', etc.
separate information, i.e. its own resource, if you want to keep the track clean. So you might get it at /tracks/:track/social_info or maybe /social_info/:track where it matches the track ID 1-to-1
If you have actual relation information, then it depends if it is 1:1 or 1:N or N:1 or N:N. 1:1 or 1:N or N:1 you would probably reports as part of the resource itself, while N:N would either be part of the resource (JSON objects can have depth) or as a separate resource.
Personally, I have done all of the above, and find cleaner is better, even if it is multiple retrievals. But now we are delving into opinion....
EDITED:
There are lots of ways to do N:N, here are just some:
/playlist/:id/tracks/:track/social_info - which could be embedded or a link to another object
/social_info/:playlist - more direct
/social_info/playlist/:id if you might have different kinds of social info
Personally (there is that word again; so much of this is personal preference and opinion), every time I have tried using deeper paths, thinking something only makes sense in a parent context, I have found myself ending up making its own resource for it, and linking back, so the 2nd or 3rd option ends up being what I do, with the first linking to it (either convenience to retrieve it or retrieve a list of it).
Mostly, that has not been because of constraints on the server side - e.g. when I write in nodejs, I use http://github.com/deitch/booster which handles multiple paths to the same resource really easily - but because client side frameworks often work better with a one true path.
If you want to fully embrace RESTful service design principles you definitely want to use hyperlinks in your representation format. JSON has some existing specifications if you prefer not to come up with your own: HAL and JSON API. A naive hypermedia format might look like this:
{
"playlist_id" : "666",
"created_at" : "2014-11-07 19:21:64",
"likes" : 5,
"tracks" : [
{"index" : 1,
"begin_at" : "00:02:00",
"end_at" : "00:05:23",
"_links" : {"track" : {
"href" : "/tracks/123",
"type" : "track"}}},
{"index" : 2,
"_links" : {"track" : {
"href" : "/tracks/432",
"type" : "track"}}},
{"index" : 3,
"_links" : {"track" : {
"href" : "/tracks/324",
"type" : "track"}}},
{"index" : 4,
"_links" : {"track" : {
"href" : "/tracks/567",
"type" : "track"}}}]
}
More elaborate features are included in both HAL and JSON API, like defining embedded resources and link templates. Using such semantics you might end up with something like the following:
{
"id" : "666",
"created_at" : "2014-11-07 19:21:64",
"likes" : 5,
"tracks" : [
{"id" : "123",
"index" : 1,
"begin_at" : "00:02:00",
"end_at" : "00:05:23"},
{"id" : "432",
"index" : 2},
{"id" : "324",
"index" : 3},
{"id" : "567",
"index" : 4}
],
"_links" : {
"_self" : {
"href" : "/playlists/666",
"type" : "playlist"},
"tracks" : {
"href" : "/tracks/{id}",
"type" : "track"}
},
"_embedded" : {
"track" : [
{"id" : "123",
"title" : "harder better faster stronger",
"artist" : "daft punk",
"created_at" : "2012-10-03 09:57:04",
"likes" : 234252,
"play_count" : 1203200035},
{"id" : "432",
"title" : "aerodynamic",
"artist" : "daft punk",
"created_at" : "2009-03-07 11:11:11",
"likes" : 33056,
"play_count" : 8796539}
]
}
}
Also, don't forget that using hyperlinks to express static relationships between entities is just the beginning of the journey. Using Hypermedia As The Engine Of Application State is the real Nirvana... but then you might be aiming too high.
Neo4j version 1.8.M06
The following query executed in the Data Browser on the web management interface returns a value for the Forename property:
start n=node(*) where ID(n)=147 return n.Forename
However the same query posted using the REST API
{
"query" :
"start n=node(*) where ID(n)={id} return n.Forename",
"params" :
{"id" : "147"}
}
Returns:
{
"columns" : [ "n.Forename" ],
"data" : [ ]
}
Any idea what I'm doing wrong?
You don't want quotes around 147 in the REST call.
Also, maybe it's because of your simplification, but I'm pretty sure you should really be doing start n=node({id}) instead, for optimum performance. Not sure if it optimizes that sort of thing out.