2023 Aug 03 8:56 AM - edited 2023 Aug 11 3:21 PM
(Check out the SAP Developer Challenge - APIs blog post for everything you need to know about the challenge to which this task relates!)
In this task you'll become acquainted with entity sets in the classic Northwind service.
You may have heard of, or even interacted with an instance of, the Northwind model and service, originally and properly called "Northwind Traders". It has a classic and well-known set of related entities and is often a first introduction for many to database schemas, OData services and more. It was originally shipped with the Microsoft Access database application.
The entities and their relationships are easy to understand and it's partly for this reason that it's so popular. In this task, you will briefly explore the Northwind service offered by OASIS Open, the non-profit standards body, where there's a working group that looks after the Open Data Protocol (OData) standard.
There are various services available at the simple landing page at https://services.odata.org and the one we will use is the OData V4 version, which is available directly at this address:
https://services.odata.org/V4/Northwind/Northwind.svc/
Your task specifically is to list the entity sets available in this service. They should be presented as a single string, following these rules:
Here's a short example of what a list should look like:
Categories,Customers,Suppliers
There are more entity sets than just these three, this is just an example.
Once you have constructed the list, you should hash it and post the hash as a new reply to this discussion thread, as described in Task 0 - Learn to share your task results. This means that to get the hash, you would need to make a call to the hash service like this (based again on the above short example), supplying your SAP Community ID in the appropriate header too:
https://developer-challenge.cfapps.eu10.hana.ondemand.com/v1/hash(value='Categories,Customers,Suppliers')
What is an entity set? It is essentially a collection (a set) of entities. There are two places where an OData service typically details the entity sets on offer. One is the service document, available at the root of the service's base URL. And the other is the metadata document, available at the service's base URL with $metadata appended. Metadata documents contain a wealth of information for an OData service; the entity set details are included, but there's a lot of other information that is included too, information that you must exclude or otherwise ignore. Simpler perhaps would be to take the service document, which has a set of collections (this harks back to the origins of OData, incidentally) which more or less equate to entity sets.
If you request the service document (https://services.odata.org/V4/Northwind/Northwind.svc/) in your browser, you get an XML based representation in response. You can parse this XML with any XML library, or command line tool (such as xmlstarlet or xmllint.
While the service document's XML structure is much simpler than the metadata document, it's still XML, and it's arguably easier these days to avoid XML altogether when doing ad-hoc parsing activities. With OData V2 services, the service document is only available in an XML representation. It's also available in a JSON representation with OData V4 services.
Using a command line HTTP client, for example, to request the service document, we get an entirely different representation.
For example, this invocation of curl:
curl \ --url "https://services.odata.org/V4/Northwind/Northwind.svc/"
returns a JSON representation, that looks like this (redacted for brevity):
{ "@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata", "value": [ { "name": "Categories", "kind": "EntitySet", "url": "Categories" }, { "name": "CustomerDemographics", "kind": "EntitySet", "url": "CustomerDemographics" }, { "name": "Customers", "kind": "EntitySet", "url": "Customers" }, { "name": "Employees", "kind": "EntitySet", "url": "Employees" }, { "name": "Order_Details", "kind": "EntitySet", "url": "Order_Details" } ] }
In case you're interested, the shell pipeline to produce this redacted representation was:
curl \ --silent \ --url "https://services.odata.org/V4/Northwind/Northwind.svc/" \ | jq '.value|=.[:5]'
Once you have a JSON representation of the service document, you can use your favorite language (JavaScript, TypeScript, Python, ABAP, or perhaps jq) to parse out the entity set names, and form them, in alphabetical order, into the comma-separated list that you need.
Of course, if you prefer to parse the XML representation of the service document, then by all means do that.
We get different representations of the service document resource, depending on where we make the request. In the browser, the representation comes back in XML form. Using curl on the command line, the representation is in JSON form. Why do you think that is?
2023 Aug 04 1:02 PM
Thanks. However, I think that at least the part
if v["kind"] == "EntitySet"
is not necessary. The service just returns EntitySets. But I just wanted to be 100% sure...
2023 Aug 04 2:48 PM
2023 Aug 03 7:29 PM - edited 2023 Aug 03 8:48 PM
2023 Aug 03 7:39 PM
2023 Aug 03 8:37 PM
Please correct me if I m wrong, the accept param in the request header defines in which form we would receive the response data and that's why we are getting different representations of the service document resource.
From chrome, the accept header param is set to application/xml for http get requests. (could be modified to receive a json response if we modify the url to https://services.odata.org/V4/Northwind/Northwind.svc/?$format=json and now the accept is set to application/json)
Similarly, for curl, the accept header param is set to application/json for http get requests. (could be modified to receive an xml response if we modify the request call to
2023 Aug 04 7:11 AM - edited 2023 Aug 04 7:18 AM
Hey @harsh_itaverma nice reply, especially your accurate use of the terms "resource" and "representation". This distinction also helps us understand what content negotiation is all about too.
Just a couple of details:
Setting $format=json on the query string of the URL does not change the Accept header value explicitly, but what it does is override whatever that Accept value happens to be (see 5.1.8 System Query Option $format in the spec).
With curl, the default Accept header is set to */*, not application/json, as you can see here:
; curl --verbose --url "https://services.odata.org/V4/Northwind/Northwind.svc/" > GET /V4/Northwind/Northwind.svc/ HTTP/1.1 > Host: services.odata.org > User-Agent: curl/7.74.0 > Accept: */*
This in turn then means that the server, having been given free range on the representation to return (the value */* effectively says "give me anything!"), will make a choice, which in this case is to return a JSON representation.
👍
2023 Aug 04 8:52 AM - edited 2023 Aug 04 8:52 AM
While replying, I was thinking of a precise word and your reply has it, which is "Default" but I wasn't sure of it.
Makes more sense now, that when using an API; we can have multiple resource representations; a default representation can be dependent on the invocation (curl, chrome, etc.) and an explicitly defined one (where we override the default one) when we specify the accept header param!
This puts in more context onto the Accept header param and how it can be important while using APIs and for content negotiation.
So much to learn from this one task of the challenge! Thanks already 🙂
2023 Aug 03 10:06 PM
2023 Aug 04 3:48 AM
2023 Aug 04 5:52 AM
2023 Aug 04 7:04 AM
2023 Aug 04 7:26 AM
2023 Aug 04 10:01 AM
2023 Aug 04 10:13 AM
2023 Aug 04 10:27 AM
2023 Aug 04 10:31 AM
2023 Aug 04 12:13 PM
2023 Aug 04 12:56 PM
Great to hear you used jq, kudos! But beware - your reply doesn't quite conform, and won't be counted. You might want to double check the instructions that describe how to post your hash 🙂
2023 Aug 04 12:57 PM - edited 2023 Aug 04 12:58 PM
I've noticed a number of you are trying out jq to help you with this task. Great! This task was deliberately simple enough to enable you to do that if you wanted. If you want more content on jq, you might want to check out this collection of posts on my blog, all tagged with jq: https://qmacro.org/tags/jq/
Happy learning!
2023 Aug 04 1:25 PM
2023 Aug 04 1:32 PM - edited 2023 Aug 04 2:47 PM
2023 Aug 04 2:11 PM
2023 Aug 04 2:22 PM
2023 Aug 04 3:31 PM
2023 Aug 04 3:42 PM
2023 Aug 04 5:09 PM
2023 Aug 04 6:47 PM
2023 Aug 04 8:17 PM
2023 Aug 04 8:55 PM
2023 Aug 04 9:39 PM
2023 Aug 05 11:13 AM
2023 Aug 05 9:18 PM
2023 Aug 06 4:10 AM
2023 Aug 06 6:26 AM - edited 2023 Aug 07 8:04 AM
2023 Aug 06 8:44 AM
2023 Aug 06 5:07 PM
2023 Aug 06 5:49 PM
2023 Aug 06 7:36 PM
2023 Aug 07 6:20 AM
2023 Aug 09 9:50 AM
It might be caused by the default call for each method being different. As mentioned in the example, the curl command line might get the output in JSON, but a browser would use an XML format instead.