Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

SAP Developer Challenge - APIs - Task 1 - List the Northwind entity sets

qmacro
Developer Advocate
Developer Advocate

(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.

Background

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

Your task specifically is to list the entity sets available in this service. They should be presented as a single string, following these rules:

  • the entity set names should be exactly as specified in the service
  • you should keep whatever case the entity set names are written in
  • the entity sets should be listed in alphabetical order
  • they should be comma-separated, with no spaces

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')

Hints and tips

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.

For discussion

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?

226 REPLIES 226

ceedee666
Active Contributor

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...

qmacro
Developer Advocate
Developer Advocate
0 Kudos

My thinking would be that if there's a `kind` property in there, that suggests there's at least a chance, however small, that there will be object entities in there that have a different value for `kind`. So I like your condition.

harsh_itaverma
Participant
0 Kudos

348c4d573615e7d93367e1a6c3ed9569e8e7086882446e3a7cd410ee2628ae9f

HJRavi
Explorer
0 Kudos

7d9e5bc1d474dd7728cc194a08cff22cd12d59499f9cb204fafee6d2dac549eb

harsh_itaverma
Participant

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 

User-Agent: curl/7.74.0
      Accept: application/xml
 
and now the response is in xml format)

Not sure if that's the reason and will wait for your response 🙂 

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.

👍

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 🙂

thomasks
Participant
0 Kudos

c953d86f79676aa086e3a48d5221c99ca15e3382bc5e6b0f190a67deb7eac43d

bztoy
Participant
0 Kudos

38e7ab7d730c8383e85d8e76fd9d1d5edef561b15a489ba4c07273e2ae86c247

msoans
Explorer
0 Kudos

8e718d98d5cf7a67b4bf7892e3559e23d52c9bf0474088007113dacab73fde1f

nmkarthikeya
Active Participant
0 Kudos

688b102a4ecd8e3ef2d2d91b530c89d51e54c6ca4f968ceae2c8c698b4a58108

StKollos
Explorer
0 Kudos

89ccf099f1148da798c4bc0b215b6906cf523098b4e79b103edfb9d66501fc71

GRABLERE
Product and Topic Expert
Product and Topic Expert
0 Kudos

65e8bbffeee67a7c2199b45ea9a5dfceb308d70eb36083b5ad4cfea07daaf708

stickman_0x00
Explorer
0 Kudos

f6151d4132e5b4d4f4c7968f388e2b8dbd1007e02ff4aada6a6f74bda8b49841

eshrinivasan
Developer Advocate
Developer Advocate
0 Kudos

79a84adf37a687fa0fd41b5c638f3a76575a9d6b022a57478a4e4adc311ebe65

qmacro
Developer Advocate
Developer Advocate
0 Kudos

🚨 Greetings folks, and well done everyone for having a go here. A lot of you have managed to get the right result, but some might want to re-check their workings. Here's how the stats look right now:

; ./runcheck 1 | ./summariseresults 
{
  "🙁": "35%",
  "🙂": "65%"
}

 

brahammittal
Explorer
0 Kudos

30da0004ea2c4f600fb97861ccb13a01edcd58d78d89ba54c6441850e4021094

Had some hard time getting it done in jq.. so learnt few things

qmacro
Developer Advocate
Developer Advocate
0 Kudos

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 🙂

qmacro
Developer Advocate
Developer Advocate

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!

brahammittal
Explorer
0 Kudos

f741393bf7871bde3edb4a4e01d132f2313362ba5ffd19aa03c5478429d538fd

prachetas
Participant
0 Kudos

0e31d22c8d3fca7d499080eb6ddadbd475385114c306355f4e54aca5399ba63b

Zakir_hussain
Explorer
0 Kudos

21383d7a051642c43724bbd764964af93f50845b381e2abc2f31c782ba804fe9

shotokka
Explorer
0 Kudos

0eb213af084704ea797b40a31edd9fe42b07c8358d0b240f94570ae9e77859ab

cdias
Product and Topic Expert
Product and Topic Expert

76e0831ae5638398fe78fd10411db6a6a9e546073fd2d104f87a32af349e6781

Ruthiel
Product and Topic Expert
Product and Topic Expert
0 Kudos

be3207f77b4a35e83f08a831023f270373e7b62aea241237df16e5cb86b3202f

se71
Participant

ff3ef3d568cab183f26fd5e18a598916575887942ccc368231fff5514b205efb

dhegde
Participant

5fa1db72dcfee3680007731e97e90e62de7fee22b38f33953b9245b9b5d5a498

Sandra_Solis
Participant

758d003c0c14b3edc35a3f811bf6e1da19e91adf66a792d5e0950179a0652d27

turanaydin
Explorer

d3f4be5c330bb49d75eb9775d8c1fed347928ffcfccfed4f1d962ad9fd43cc98

P41l
Explorer

d4d51c6e1e6983c09a061223383a1032aecba3fa936f53b30e916316f5a6d0a5

BrijeshGandhi
Explorer
0 Kudos
d40544b2c10e1266b102e2a83f4f5599a48c4832b7bfbc1457e8e77c97207642

MioYasutake
Active Contributor
0 Kudos

21db3333a071721ded856f0b4a1ec1e9664fec3caf98a09d65a630642ff669ff

ajos
Explorer
0 Kudos

336750df759002c7ba2329bc5b96ec4516d884686bffc4a4180145a60eb903f9

Dan_Wroblewski
Developer Advocate
Developer Advocate
0 Kudos

9a0a8759d0db7529f2352ea225a861d3e4fc0cf57e391e846018e339b6f6653e

 




--------------
See all my blogs and connect with me on Twitter / LinkedIn

gphadnis2000
Participant
0 Kudos

1d4ffb1e7536dc1e9e3444b49fcf413753e0ec3b4cc16b40d84a5bf9c1973cfa

eakucuk
Explorer
0 Kudos

d912c544464be0783c44d4bea0c4ca0d34030786bb926b2a7b67576deddff728

sgatea
Discoverer
0 Kudos

7276eb35f2866fcdad5575e604ed862ba27252a4d6959ed3cb890bf75e000b0e

AbapAndy728
Explorer
0 Kudos

ea530b44f1ad16e17470ef25aa28e6ebba6532a8d20ba88bb64f3681963e0d66

choujiacheng
Explorer
0 Kudos

9e44ca060d6793e70898ca949b954c00c38da3ac9f95238ece2014236b0bb655

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.