I'm wondering if the following structure of API links is HATEOAS compatible?
Especially I'm not sure of /create endpoint. Should it be at the entry level because user can create a group from there or is it fine to put it in /groups?
What are your thoughts about the rest? It should be also HAL compatible.
/groups
/create
/detail/{groupId}
/update
/delete
/items
/search{?page,size,sort}
HATEOAS (see Richardson's Maturity Model level 3) is all about links, so with HAL Browser this would look something like this:
Root:
{
"_links": {
"self": {
"href": "/api/root"
},
"api:group-add": {
"href": "http://apiname:port/api/group"
},
"api:group-search": {
"href": "http://apiname:port/api/group?pageNumber={pageNumber}&pageSize={pageSize}&sort={sort}"
},
"api:group-by-id": {
"href": "http://apiname:port/api/group/id" (OR "href": "http://apiname:port/api/group?id={id}")
}
}
}
The add would simply be a POST to that endpoint, and then you'd have 2 GET methods.
Then once you drill down to a particular group (say #1):
{
"Id" : 1,
"Name" : "test",
"_links": {
"self": {
"href": "/api/group/1" (OR "/api/group?id=1")
},
"edit": {
"href": "http://apiname:port/api/group/1"
},
"api:delete": {
"href": "http://apiname:port/api/group/1"
},
"api:items-query": {
"href": "http://apiname:port/api/bonus?groupId=1"
}
}
}
Here, the edit would simply be a PUT, and then you'll need a DELETE (see level 2 of REST in that same link), as for the items, you probably know best if they are just a property, or another endpoint; you could even embed them to be returned in the same call that's retrieving a group.
Related
I want to change the status of the project issue on Jira. The status is Open and I want to make it Fixed. My url is PUT https://jiradbg-sandbox.deutsche-boerse.de/rest/api/latest/issue/PID-XX
{
"update": {
"fields":{
"status": [
{
"set": "Fixed"
}
]
}
}
}
and the response is:
{
"errorMessages": ["Can not deserialize instance of java.util.ArrayList out of START_OBJECT token\n at [Source: org.apache.catalina.connector.CoyoteInputStream#5de98556; line: 3, column: 9]
(through reference chain: com.atlassian.jira.rest.v2.issue.IssueUpdateBean[\"update\"])"]
}
There are two problems that you are encountering here.
The first problem is update or fields should be provided separately to Jira's edit issue API, not one inside of the other. They have equivalent functionality so normally only one is used. For example to update the summary field provide either update:
{
"update": {
"summary": [
{
"set": "Updated by update"
}
]
}
}
or fields:
{
"fields": {
"summary": "Summary set by fields"
}
}
However the status field is a special case and can't be updated directly, which is the second problem here. Changing a status in Jira is called a transition. You need to trigger the transition to move the issue into the status you want.
Start by identifying the available transitions by calling the get transitions API:
GET https://example.net/rest/api/latest/issue/PID-XX/transitions
This tells you which transitions are currently available, something like this:
{
"expand": "transitions",
"transitions": [
{
"id": "21",
"name": "Fixed",
"to": {
"self": "https://example.net/rest/api/2/status/10001",
"description": "",
"iconUrl": "https://example.net/images/icons/status_generic.gif",
"name": "Fixed",
"id": "10001",
"statusCategory": {
"self": "https://example.net/rest/api/2/statuscategory/3",
"id": 3,
"key": "done",
"colorName": "green",
"name": "Done"
}
}
}
]
}
Take the id of the transition you want, in this case 21, then post it to the issue transition API:
POST https://example.net/rest/api/latest/issue/PID-XX/transitions
Use a request body like this:
{
"transition": {
"id": 21
}
}
You should get a 204 HTTP response from Jira which indicates the transition was successful.
I am trying to use not in operator in odata.
So does it support or not?
If yes then could you please give some example.
I was going through this post and trying but could not success.
https://github.com/OData/odata.net/issues/1478
the comments in the linked git hub issue https://github.com/OData/odata.net/issues/1478 actually demonstrates that there are variations of support for NOT IN, even though there is not a single operator for it.
The .Net implementation of OData v4 does support the IN Operator for arrays of discreetly defined values, it does not Support a NOT-IN style operator but it does have support for both NOT and IN.
NOT simply negates the expression result but we can also replicate the NOT functionality by equating the expression result with false.
I can't find a publicly available sample to share, but my local projects do not have any trouble with the following queries:
IN
Although redundant, the second query demonstrates that the result of IN is a boolean expression and that you can further chain that expression with further conditions.
~/OData/Facilities?$filter=Entity/Title in ('Abbotsford','test')
~/OData/Facilities?$filter=Entity/Title in ('Abbotsford','test') eq true
returns:
{
"#odata.context": "http://localhost:16486/odata/$metadata#Facilities(FacilityType,Id,Entity(Title))",
"value": [
{
"FacilityType": "None",
"Id": 1081,
"Entity": {
"Title": "Abbotsford"
}
},
{
"FacilityType": "None",
"Id": 2009,
"Entity": {
"Title": "test"
}
},
{
"FacilityType": "None",
"Id": 8046,
"Entity": {
"Title": "test"
}
}
]
}
NOT IN
~/OData/Facilities?$filter=not(Entity/Title in ('Abbotsford','test'))
~/OData/Facilities?$filter=Entity/Title in ('Abbotsford','test') eq false
{
"#odata.context": "http://localhost:16486/odata/$metadata#Facilities(FacilityType,Id,Entity(Title))",
"value": [
{
"FacilityType": "None",
"Id": 1065,
"Entity": {
"Title": "Sleepy Hollow Templestowe Lower"
}
},
{
"FacilityType": "None",
"Id": 13076,
"Entity": {
"Title": "Peach Meadows"
}
}
]
}
If you model has addressable collection or array
I am trying to import some data programatically into contentful:
I am following the docs here
And running the command inside my integrated terminal
contentful space import --config config.json
Where the config file is
{
"spaceId": "abc123",
"managementToken": "112323132321adfWWExample",
"contentFile": "./dataToImport.json"
}
And the dataToImport.json file is
{
"data": [
{
"address": "11234 New York City"
},
{
"address": "1212 New York City"
}
]
}
The thing is I don't understand what format my dataToImport.json should be and what is missing inside this file or in my config file so that the array of addresses from the .json file get added as new entries to an already created content model inside the Contentful UI show in the screenshot below
I am not specifying the content model for the data to go into so I believe that is one issue, and I don't know how I do that. An example or repo would help me out greatly
The types of data you can import are listed : in their documentation
your json top level should say "entries" and not data, if new content of a content type is what you would like to import.
This is an example of a blog post as per content model of the tutorial they provide.
The only thing i didn't work out yet is where the user id is :D so i substituted for one of the content type 'person' also provided in their tutorial (I think it's called Gatsby Starter)
{"entries": [
{
"sys": {
"space": {
"sys": {
"type": "Link",
"linkType": "Space",
"id": "theSpaceIdToReceiveYourImport"
}
},
"type": "Entry",
"createdAt": "2019-04-17T00:56:24.722Z",
"updatedAt": "2019-04-27T09:11:56.769Z",
"environment": {
"sys": {
"id": "master",
"type": "Link",
"linkType": "Environment"
}
},
"publishedVersion": 149, -- these are not compulsory, you can skip
"publishedAt": "2019-04-27T09:11:56.769Z", -- you can skip
"firstPublishedAt": "2019-04-17T00:56:28.525Z", -- you can skip
"publishedCounter": 3, -- you can skip
"version": 150,
"publishedBy": { -- this is an example of a linked content
"sys": {
"type": "Link",
"linkType": "person",
"id": "personId"
}
},
"contentType": {
"sys": {
"type": "Link",
"linkType": "ContentType",
"id": "blogPost" -- here should be your content type 'RealtorProperties'
}
}
},
"fields": { -- here should go your content type fields, i can't see it in your post
"title": {
"en-US": "Test 1"
},
"slug": {
"en-US": "Test-1"
},
"description": {
"en-US": "some description"
},
"body": {
"en-US": "some body..."
},
"publishDate": {
"en-US": "2016-12-19"
},
"heroImage": { -- another example of a linked content
"en-US": {
"sys": {
"type": "Link",
"linkType": "Asset",
"id": "idOfTHisImage"
}
}
}
}
},
--another entry, ...]}
Have a look at this repo. I am also trying to figure this out. Looks like there's quite a lot of fields that need to be included in the json file. I was hoping there'd be a simple solution but it seems you (me too actually) will need to create scripts to "convert" your json file to data contentful can read and import.
I'll let you know if I find anything better.
I got hal formatted response as this:
{
"name": "Publisher A",
"bookPublishers": [
{
"publishedDate": "2019-07-12T08:19:04.583+0000",
"_links": {
"publisher": {
"href": "http://localhost:8080/api/publishers/1"
},
"book": {
"href": "http://localhost:8080/api/books/2"
}
}
},
{
"publishedDate": "2019-07-12T08:19:04.564+0000",
"_links": {
"publisher": {
"href": "http://localhost:8080/api/publishers/1"
},
"book": {
"href": "http://localhost:8080/api/books/1"
}
}
}
],
"_links": {
"self": {
"href": "http://localhost:8080/api/publishers/1"
},
"publisher": {
"href": "http://localhost:8080/api/publishers/1"
},
"friends": {
"href": "http://localhost:8080/api/publishers/1/friends"
},
"createdBy": {
"href": "http://localhost:8080/api/publishers/1/contact"
}
}
}
I see there property bookPublishers and also in links friends. Imho they should be both association links (see 2.4. Creating the Associations) where can I "put" another resources.
I would like to make spring render bookPublishers same as friends.
Sample project is here: https://github.com/luvarqpp/poc-springHalRelations
You can do:
git clone https://github.com/luvarqpp/poc-springHalRelations.git
cd poc-springHalRelations
mvn clean spring-boot:run
And than open http://localhost:8080/api
PS: Bonus question, what is easiest way to provide own relation for business logic, like relation "renameAuthor" for example.
For collection relationships, Spring Data will provide a link when a repository exists for the relevant type. Where no repository exists then the collection will be in-lined in the response, otherwise, how else will the client get the data.
Therefore, create a repository for your BookPublisher type.
Relevant documentation part citation:
the component responsible for creating the links to referenced entities (such as those objects under the _links property in the object’s JSON representation). It takes an #Entity and iterates over its properties, creating links for those properties that are managed by a Repository and copying across any embedded or simple properties.
You can also create a projection that would in-line the data when required. Clients could specify this projection in the request therefore preventing an additional server call.
e.g.
/publisher/1?projection=withBookPublishers.
https://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts.projections
In the json:api format relationships are defined with a type and a id.
Like in the example bellow. The article has a relationship with the type people and the id 9.
Now if i want to fetch the related resource i use the URI from "links.related"
// ...
{
"type": "articles",
"id": "1",
"attributes": {
"title": "Rails is Omakase"
},
"relationships": {
"author": {
"links": {
"self": "http://example.com/articles/1/relationships/author",
"related": "http://example.com/articles/1/author"
},
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/articles/1"
}
}
// ...
But in my case the related resource (people) are in a separate API. There is no way to get the full people data from the articles API nor is it possible to include it. The only way to get the related data would be a call to:
http://example.com/v1-2/people/9/
Where can i define the relation between the URI and people:9
Or in other words: How would a client know where to fetch the related resource?