I could not find detailed documentation about Entity Service and Service Path, this is best i could find is this section in the Orion User Manual
I would like to retrieve a "Fiware-ServicePath" for a specific Entity_ID but NGSI10 does not provide that information using queryContext.
Is there a way of retrieving this information ?
My process is described here, everything is working except the the Get ServicePath using EntityID part:
A gateway is pushing data into Orion and i would like to make to "update or insert procedure":
Get ServicePath using EntityID
IF exists: update it
If not exists: updatecontext with ServicePath '/NewItems'
As a workaround, I would add the ServicePath into some metadata...
You can add Fiware-ServicePath: /NewItems to the query request in order to check if the entity is in that service path or not. You can also add a comma-separated list, e.g. Fiware-ServicePath: /NewItems1, /NewItems2.
This approach would work except if the entity can be in any service path (even diffent to the "/NewItems" that is going to be use to create entity failing the existence checking) and you don't know them in advance.
In that case, the workaround by the moment is as you say, to store the service path associated to the entity, although my recomendation is to use an entity attribute for that, not a metadata (note that in NGSI metadata are associated to attributes, not entity themselves).
Related
I read a lot about each and every function of those mentioned in the title,
But I always have doubt that what is the primary use of all individual functions. Can someone explain to me in detail? Thank you.
What is the use of all GET, PUT, DELETE when anything can be done by POST
This is a pretty important question.
Note that, historically, SOAP essentially did everything by POST; effectively reducing HTTP from an application protocol to a transport protocol.
The big advantage of GET/PUT/DELETE is that the additional semantics that they promise (meaning, the semantics that are part of the uniform interface agreed to by all resources) allow us to build general purpose components that can do interesting things with the meta data alone, without needing to understand anything specific about the body of the message.
The most important of these is GET, which promises that the action of the request is safe. What this means is that, for any resource in the world, we can just try a GET request to "see what happens".
In other words, because GET is safe, we can have web crawlers, and automated document indexing, and eventually Google.
(Another example - today, I can send you a bare URI, like https://www.google.com and it "just works" because GET is understood uniformly, and does not require that we share any further details about a payload or metadata.)
Similarly, PUT and DELETE have additional semantic constraints that allow general purpose components to do interesting things like automatically retry lost requests when the network is unreliable.
POST, however, is effectively unconstrained, and this greatly restricts the actions of general purpose components.
That doesn't mean that POST is the wrong choice; if the semantics of a request aren't worth standardizing, then POST is fine.
In API perspective,
GET - It is to retrieve record/data from a source. API would need no data from client/UI to retrieve all records , or would need query param / path param to filter records based on what is required - either record with a particular ID or other properties.
POST - it is to store a new record at a source . API would get that record from client/UI through request body and store it.
PUT - it is to update an existing record at a source . API would receive updated record along with Id and update it with existing record whose id match with one passed from UI.
DELETE - it is to delete a record present in source. UI would send nothing to delete whole all records at source or send id to remove a particular record.
Source refers to any database.
I need to store the values of devices' attributes with the right type in OrionCB's MongoDB.
As I was unable to perform that I dived into the code and found that IoTAgentUL (as well as IoTAgentJSON) uses OrionCB's API v1 instead of API v2.
As I can see API v1's updateContext sends data to MongoDB without it's type, so every measure is stored as text.
In the other hand I found that API v2's update entity send data to MongoDB with it's type. It produces that I can store attribute's values with it's type which benefits me when manipulating data (i.e. creating indexes, sorting, etc).
My question is if is there any workaround to solve this using the current implementations of IoT Agents.
The only workaround I can imagine is, once entities are automatically created by the IoT Agents, to update the type of such entities by your own. I mean, AFAIK, you can update both the value and the type of an entity.
In more details, I can think on a script that subscribes for all entities of certain type (those created by the agents). Then, when an entity is created this is notified to the script, which automatically updates the type of the entity's attributes.
Please observe you only need to modify the attribute's types once, just when the entities are created, not when an entity's attribute is updated; thus, something like an array or cache of already modified entities is needed in your script.
I'm using WSO2 Products, IS and API Gateway.
My use case is : I have a ReadOnly LDAP User Store that have some attributes such name, surname, email etc.. Obviously in LDAP Read Only i can't add new user's property, for example I would like to add a attribute (claime) with name "Profile". I found some documentation but i don't understand how to do this. (https://docs.wso2.com/display/IS510/Writing+a+Custom+User+Store+Manage).
If I understand well, I have to create a new User Store (such MYSQL DB) where i can mapping the LDAP's users and i can also add custom attribute.
This is the right way to do it?
And another question is : If the consideration above is right, How can I do provisioning of the 2 User Store ?
One way to do it without any code is as follows.
Create a new claim in WSO2 according to your preference, e.g. "Profile".
Map this claim to an existing unused attribute of your ReadOnly LDAP.
e.g. Map profile to FAX or Street Addres etc.
Modify configuration of your service provider and send this new claim in authentication response to your service provider.
Now you can update this LDAP attribute with whatever value you want and Service Provider will receive this as claim named as "profile".
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Now the API-extension in question:
GET: items?filter - Returns all item ids matching the filter
PUT: items - Updates or creates a set of items as described by the JSON payload
[[DELETE: items - deletes a list of items described by JSON payload]] <- Not Correct
I am now being interested in the DELETE and PUT operation recycling functionality that can be easily accessed by PUT/DELETE items/{id}.
Question: Is it common to provide an API like this?
Alternative: In the age of Single Connection Multiple Requests issuing multiple requests is cheap and would work more atomic since a change either succeeds or fails but in the age of NOSQL database a change in the list might already have happend even if the request processing dies with internal server or whatever due to whatever reason.
[UPDATE]
After considering White House Web Standards and Wikipedia: REST Examples the following Example API is now purposed:
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Top-resource API:
GET: items?filter - Returns all item ids matching the filter
POST: items - Updates or creates a set of items as described by the JSON payload
PUT and DELETE on /items is not supported and forbidden.
Using POST seems to do the trick as being the one to create new items in an enclosing resource while not replacing but appending.
HTTP Semantics POST Reads:
Extending a database through an append operation
Where the PUT methods would require to replace the complete collection in order to return an equivalent representation as quoted by HTTP Semantics PUT:
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being returned in a 200 (OK) response.
[UPDATE2]
An alternative that seems even more consistent for the update aspect of multiple objects seems to be the PATCH method. The difference between PUT and PATCH is described in the Draft RFC 5789 as being:
The difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. The PATCH method affects the resource identified by the Request-URI, and it also MAY have side effects on other resources; i.e., new resources may be created, or existing ones modified, by the application of a PATCH.
So compared to POST, PATCH may be also a better idea since PATCH allows an UPDATE where as POST only allows appending something meaning adding without the chance of modification.
So POST seems to be wrong here and we need to change our proposed API to:
A simple REST API:
GET: items/{id} - Returns a description of the item with the given id
PUT: items/{id} - Updates or Creates the item with the given id
DELETE: items/{id} - Deletes the item with the given id
Top-resource API:
GET: items?filter - Returns all item ids matching the filter
POST: items - Creates one or more items as described by the JSON payload
PATCH: items - Creates or Updates one or more items as described by the JSON payload
You could PATCH the collection, e.g.
PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]
Technically PATCH would identify the record in the URL (ie PATCH /items/1 and not in the request body, but this seems like a good pragmatic solution.
To support deleting, creating, and updating in a single call, that's not really supported by standard REST conventions. One possibility is a special "batch" service that lets you assemble calls together:
POST /batch
[
{ method: 'POST', path: '/items', body: { title: 'foo' } },
{ method: 'DELETE', path: '/items/bar' }
]
which returns a response with status codes for each embedded requests:
[ 200, 403 ]
Not really standard, but I've done it and it works.
Updating Multiple Resources With One Request - Is it standard or to be avoided?
Well, sometimes you simply need to perform atomic batch operations or other resource-related operations that just do not fit the typical scheme of a simple REST API, but if you need it, you cannot avoid it.
Is it standard?
There is no universally accepted REST API standard so this question is hard to answer. But by looking at some commonly quoted api design guidelines, such as jsonapi.org, restfulapi.net, microsoft api design guide or IBM's REST API Conventions, which all do not mention batch operations, you can infer that such operations are not commonly understood as being a standard feature of REST APIs.
That said, an exception is the google api design guide which mentions the creation of "custom" methods that can be associated via a resource by using a colon, e.g. https://service.name/v1/some/resource/name:customVerb, it also explicitly mentions batch operations as use case:
A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response. [...] Custom methods should use HTTP POST verb since it has the most flexible semantics [...] For performance critical methods, it may be useful to provide custom batch methods to reduce per-request overhead.
So in the example case you provided you do the following according to google's api guide:
POST /api/items:batchUpdate
Also, some public APIs decided to offer a central /batch endpoint, e.g. google's gmail API.
Moreover, as mentioned at restfulapi.net, there is also the concept of a resource "store", in which you store and retrieve whole lists of items at once via PUT – however, this concept does not count for server-managed resource collections:
A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them. A store never generates new URIs. Instead, each stored resource has a URI that was chosen by a client when it was initially put into the store.
Having answered your original questions, here is another approach to your problem that has not been mentioned yet. Please note that this approach is a bit unconventional and does not look as pretty as the typical REST API endpoint naming scheme. I am personally not following this approach but I still felt it should be given a thought :)
The idea is that you could make a distinction between CRUD operations on a resource and other resource-related operations (e.g. batch operations) via your endpoint path naming scheme.
For example consider a RESTful API that allows you to perform CRUD operations on a "company"-resource and you also want to perform some "company"-related operations that do not fit in the resource-oriented CRUD-scheme typically associated with restful api's – such as the batch operations you mentioned.
Now instead of exposing your resources directly below /api/companies (e.g. /api/companies/22) you could distinguish between:
/api/companies/items – i.e. a collection of company resources
/api/companies/ops – i.e. operations related to company resources
For items the usual RESTful api http-methods and resource-url naming-schemes apply (e.g. as discussed here or here)
POST /api/companies/items
GET /api/companies/items
GET /api/companies/items/{id}
DELETE /api/companies/items/{id}
PUT /api/companies/items/{id}
Now for company-related operations you could use the /api/companies/ops/ route-prefix and call operations via POST.
POST /api/companies/ops/batch-update
POST /api/companies/ops/batch-delete
POST /api/companies/ops/garbage-collect-old-companies
POST /api/companies/ops/increase-some-timestamps-just-for-fun
POST /api/companies/ops/perform-some-other-action-on-companies-collection
Since POST requests do not have to result in the creation of a resource, POST is the right method to use here:
The action performed by the POST method might not result in a resource that can be identified by a URI.
https://www.rfc-editor.org/rfc/rfc2616#section-9.5
As far as I understand the REST concept it covers an update of multiple resources with one request. Actually the trick here is to assume a container around those multiple resources and take it as one single resource. E.g. you could just assume that list of IDs identifies a resource that contains several other resources.
In those examples in Wikipedia they also talk about resources in Plural.
I am trying to build my application's admin UI using sling's userManager REST interface, but I would like to customize the json rendering. For example, I would like the response of "Get group" to include the members only if the requestor is a member.
I started by adding libs/sling/group/json.esp but I don't understand how I can get hold of the default response and customize it. Even if I had to query and form the json from scratch, where can I find information about APIs available to get this data from JCR/Sling?
I found that I could use ResourceTraversor to dump the resource object in json form but using new Packages.org.apache.sling.servlets.get.impl.helpers.ResourceTraversor(-1, 10000, resource, true) in the esp throws up an error
There are a few things to note here.
First, you should avoid putting your code under the libs directory. Your app code should live under the apps directory. When attempting to resolve a servlet for a URI, Sling will check apps before it checks libs so if you need to completely override functionality delivered with Sling, you would place your code in apps.
Second, what is (probably, depending on how you have things setup) happening when you request http://localhost:8080/system/userManager/group/administrators.tidy.1.json is the request is being handled by Sling's default GET servlet, because it finds no other script or servlet which is applicable. For research purposes it might be worth looking at the code for the default get servlet, org.apache.sling.servlets.get.impl.DefaultGetServlet, to see what it's using to render JSON. If you need to handle the rendering of a user group in a manner different than what the default GET servlet is doing, then you would need to create a servlet which is listening for requests for resources of type sling/group. It would probably be ideal to create a servlet for this purpose and register it with OSGI. http://sling.apache.org/site/servlets.html provides the various properties you would need to set to ensure the servlet resolver finds your servlet. Your servlet then would handle the request and as such would have direct and easy access to the requested resource.
Third, the particular need you specified is that you do not want the group members to render unless the requesting user is a member of the group requested. This is more of an access control issue than a rendering issue. Sling and Jackrabbit, out of the box, make as few assumptions as possible concerning how you might want your application to be setup. That being the case, you need to establish the access controls that are applicable for your particular use case. The wiki post on Access Control in the Jackrabbit wiki ( http://wiki.apache.org/jackrabbit/AccessControl ) goes into this to an extent.
Using directions from Paul Michelotti's answer, I researched further and found a suitable solution to my problem.
Sling accepts request filters (javax.servlet.Filter) through SCR annotations like the one below
#SlingFilter(scope = SlingFilterScope.REQUEST, order = Integer.MIN_VALUE)
Every request is passed down to the filter before it is processed by the servlet. Using the resourceType, I was able to distinguish requests to group.1.json and group/mygroup.1.json. Since the filter also has access to the current user, I was able to decide to deny the request if it did not abide by my security model and return a 404 status code.
Please refer to this page for details on filters. You can also check out the sample project urlfilter for directions on usage.