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: 

Task 8 - Responding to an OData query with navigation (July Developer Challenge - "Reverse APIs")

qmacro
Developer Advocate
Developer Advocate
3,886

This is a task in the July Developer Challenge - "Reverse APIs".

This time, a simple one that should take you no time! After the previous task where you created a brand new Northbreeze service, complete with data (right?), as well as implementing the first API endpoint in that new service, this task is designed to give you a bit of a break, and to allow you to reflect on the power that CAP gives you out of the box, and on just some of the many wondrous aspects of OData.

Background

With all the functions and actions you've had to define and implement so far, it's easy to forget what CAP gives you for free, when creating and serving services. And in terms of support for OData, a very accomplished and "complete" protocol, it is second to none, particularly with regards to the mechanisms you get for free.

The requirements

Here are the specific requirements for this task. Your Northbreeze service, still served via the OData V4 protocol, must respond appropriately to an OData QUERY operation that expresses a navigation from one entity to a related one, in the resource path. Specifically, it must respond to a request for an entity set of the Products belonging to a particular Supplier (see the Northwind and Northbreeze section of the previous task for details on these entity types).

In other words, your service needs to return an entity set containing products, for a specific supplier.

Some examples

Using the standard Northwind service, here are a couple of examples of that.

First, a list of the products belonging to the supplier with ID 22 ("Zaanse Snoepfabriek"): /Suppliers(22)/Products, which should produce:

{
  "@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Products",
  "value": [
    {
      "ProductID": 47,
      "ProductName": "Zaanse koeken",
      "SupplierID": 22,
      "CategoryID": 3,
      "QuantityPerUnit": "10 - 4 oz boxes",
      "UnitPrice": 9.5000,
      "UnitsInStock": 36,
      "UnitsOnOrder": 0,
      "ReorderLevel": 0,
      "Discontinued": false
    },
    {
      "ProductID": 48,
      "ProductName": "Chocolade",
      "SupplierID": 22,
      "CategoryID": 3,
      "QuantityPerUnit": "10 pkgs.",
      "UnitPrice": 12.7500,
      "UnitsInStock": 15,
      "UnitsOnOrder": 70,
      "ReorderLevel": 25,
      "Discontinued": false
    }
  ]
}
Next, the products for supplier "Tokyo Traders" (ID 4), but just the product name and unit price: /Suppliers(4)/Products?$select=ProductName,UnitPrice, which should produce:
{
  "@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Products(ProductName,UnitPrice)",
  "value": [
    {
      "ProductName": "Mishi Kobe Niku",
      "UnitPrice": 97.0000
    },
    {
      "ProductName": "Ikura",
      "UnitPrice": 31.0000
    },
    {
      "ProductName": "Longlife Tofu",
      "UnitPrice": 10.0000
    }
  ]
}

Back to the requirements

So your service must do this too. The great thing is, if you've set up your Northbreeze service as I recommended in the previous task (i.e. starting from a clone of the Northbreeze repo, then you're already set, and don't need to do anything specific to have the TESTER successfully test this in your service. That's thanks to the power of CAP.

The service must be served using the OData V4 protocol, with the (default) path prefix /odata/v4 plus the service name northbreeze, and return an entity set of products belonging to a given supplier. Those products must be the correct ones (for example, products "Zaanse koeken" and "Chocolade" are the two products for supplier "Zaanse Snoepfabriek" (ID 22) and have the same IDs as they have in Northwind (as the TESTER will be checking the products returned in the entity set and examining the order of their IDs).

And that's it!

As there is, in theory, nothing more for you to do in this task (except to submit to the TESTER as usual, see below), if you've correctly implemented the service for the previous task already, then why not use the remainder of your coffee time to consider the power of OData, and think about the answers to the following questions:

First, the Northwind service only allows the "traditional" OData key specification in the the resource path, e.g. /Suppliers(7) and not the more recent Key-as-Segment style. Does your Northbreeze service, powered by CAP, support that? What does that look like?

While we're talking about resource paths, what about going one level deeper - is that supported? For example, Northwind supports paths such as /Products(70)/Category/CategoryName to get just the name of the category to which the product with ID 70 belongs. Does CAP support that too - can you do it with your Northbreeze service?

Even what one might think should be single scalar value responses, such as a category name like Beverages, come delivered inside some wrapping, by default in either an XML representation in the case of Northwind (extra whitespace added for readability):

<m:value 
    xmlns:d="http://docs.oasis-open.org/odata/ns/data" 
    xmlns:georss="http://www.georss.org/georss" 
    xmlns:gml="http://www.opengis.net/gml" 
    xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" 
    m:context="https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Products(70)/Category/CategoryName">
    Beverages
</m:value>
or in a JSON representation in the case of the CAP powered Northbreeze equivalent:
{
  "@odata.context": "../../$metadata#Categories(1)/CategoryName",
  "value": "Beverages"
}
What if you wanted just the scalar value Beverages? Is that possible? If so, how?

On these questions and any related ones that occur to you - be sure to put your thoughts in the comments below!

Submitting to the TESTER

Now you're ready to submit your CANDIDATE service to the TESTER!

The payload

The task identifier you need to supply in the payload of your submission is: northbreeze-Products.

You'll have already done this sort of thing previously so just head back there for the more detailed instructions if you need them, or to the the section titled "The Tester service, and making a test request" in the main challenge blog post.

You'll need to submit a JSON payload like this:

{
  "communityid": "<your-community-id>",
  "serviceurl": "<the-URL-of-your-service>",
  "task": "northbreeze-Products"
}
And, just as with the previous (and all further tasks):
  • the value for the communityid property should be your ID on this SAP Community platform (e.g. mine is "qmacro")

  • the value for the serviceurl property should be the absolute URL (i.e. including the scheme), of your CANDIDATE service.

That's it!

Logging of test results

Remember that you can check on your progress, and the progress of your fellow participants - all requests are logged and are available in an entity set served by the TESTER service. The entity set URL is https://developer-challenge-2024-07.cfapps.eu10.hana.ondemand.com/tester/Testlog and being an OData V4 entity set, all the normal OData system query options are available to you for digging into that information.

Until the next task, have fun, and if you have any questions or comments, leave them below!

34 REPLIES 34

Liyon_SV
Explorer
3,735

Still thinking about those additional questions.

Liyon_SV_0-1721808728612.png

 

cguttikonda24
Participant
3,714

Hello DJ @qmacro ,

Here is my observation.

1. Calling the entity with  Key-as-Segmen is possible in CAP, as it is supporting oData v4 out-of the box.

2 To read just the scalar values, we can use the $value get the data.

odata/v4/northbreeze/Products/11/Category/CategoryName/$value

cguttikonda24_0-1721811368700.png

 

3,702

Excellent! Thanks for providing your thoughts. 

It's worth mentioning here that it's possible to use key-as-segment addressing CAP, not because CAP supports OData V4 out of the box, just that CAP supports this optional alternate convention. The Northwind service at https://services.odata.org/V4/Northwind/Northwind.svc/ doesn't support that, but it's still an OData V4 service.

Also, I can't resist pointing out that it's "OData", not "oData" 🙂

mxmw
Explorer
3,594

This easy one is a nice time to catch a breathe after the amount of troubleshooting on the previous:

mxmw_0-1721820205971.png

 

In regards to the questions I have played a little bit around with the endpoints and came to the same conclusion as cguttikonda24.

Especially properly amazed by the ease of SAP CAP for creating services with all features that you can wish for.

qmacro
Developer Advocate
Developer Advocate
0 Kudos
3,576

Good to hear!

YogSSohanee
Participant
0 Kudos
3,509

Hello @qmacro ,

I am getting an error as below when i am trying to call URL - 

GET {{baseURL}}/odata/v4/northbreeze/Products/11

YogSSohanee_0-1721852864664.png

 

Does this mean that the service is not implemented properly, kindly suggest!

 

3,506

Hi @YogSSohanee ,

I faced the same issue in the previous task. In my case, at the end of my event handler code, I wrote `return super.init`, but it had to be corrected to `return super.init()`.

 

qmacro
Developer Advocate
Developer Advocate
0 Kudos
3,276

Nice one @MioYasutake - yes, this is likely the cause.

0 Kudos
3,191

Hi @MioYasutake , bang on! That was the problem, a mere typo. 🙂 Thanks for your help!

@qmacro : Please find below my submission for Task 8.

YogSSohanee_1-1721918292222.png

 

Tried few OData calls and its in line with the regular OData calls.

YogSSohanee_0-1721918229892.png

 

YogSSohanee_2-1721918469533.png

 

YogSSohanee_3-1721918592349.png

 

 

 

MioYasutake
Active Contributor
3,506

My submission for task 8.

MioYasutake_0-1721854240562.png

 

Alpesa1990
Participant
3,500

My submission for task 8.

 

Alpesa1990_0-1721855339565.png

 

sudarshan_b
Participant
3,350

Here's my submission for task 8 - 

 

sudarshan_b_0-1721900085749.png

The Key-as-segment convention is new learning for me, however I somehow see it similar to the cds.ql option of WHERE clause, like in example SELECT.from (Books,201), I may be completely wrong though 🙂

qmacro
Developer Advocate
Developer Advocate
0 Kudos
3,276

Thanks for the thoughts, @sudarshan_b ! 

geek
Participant
3,330

geek_0-1721899942597.png

geek_1-1721900079778.png

No issues deploying this one...

While we're talking about resource paths, what about going one level deeper - is that supported?

geek_2-1721900776292.png

What if you wanted just the scalar value Beverages? Is that possible? If so, how?

Following the instructions from Task 7:

geek_5-1721901195512.png

First, the Northwind service only allows the "traditional" OData key specification in the the resource path, e.g. /Suppliers(7) and not the more recent Key-as-Segment style. Does your Northbreeze service, powered by CAP, support that? What does that look like?

geek_4-1721901082312.png

qmacro
Developer Advocate
Developer Advocate
0 Kudos
3,270

Great answer / comment, thanks!

MatLakaemper
Participant
3,117

my Submission, 

Scalar-Value: 

MatLakaemper_0-1721924599507.png

MatLakaemper_1-1721924631208.png

MatLakaemper_2-1721924642533.png

 

 

 

 

 

vineelaallamnen
Explorer

gphadnis2000
Participant
2,963

My submission for Task 8

gphadnis2000_0-1721953145329.png

 

AndrewBarnard
Contributor
2,942

There must be a lot of people with big brains in the CAP team! Despite CAP growing larger in capabilities, there is a remarkable degree of conceptual consistency. Kudos!
Oh - did you know the earliest usage of kudos in the english language is rather recent, around the 1830's according to the Oxford English Dictionary?  

0 Kudos
2,854

I can confirm: there _are_ a lot of people with big brains in the CAP team 🙂

On "kudos", that's right. Unfortunately (and much to the annoyance of my pedantic side (of which I'm very proud)), "kudo" (no "s") is not a word, Kudos is a mass noun and cannot be subdivided, i.e. the "s" doesn't denote plural, and by inference any lack of "s" doesn't denote singular, and it makes me sad every time I see it 🙂

Screenshot 2024-07-26 at 13.21.35.png

JimSpath
Active Contributor
2,691

There's languages and there's languages. Compilers can enforce strict grammars. Street lingo, on the other hand, evolves organically rather than by version releases. 

https://www.merriam-webster.com/dictionary/kudo

I primarily bemoan that forte has 2 syllables now.

qmacro
Developer Advocate
Developer Advocate
0 Kudos
2,514

The "evolves organically" argument is partly true but partly missing the point, IMHO. I mention this in my post Accuracy and precision in language

The reference in MW is another (of quite a few) reasons why I don't hold that dictionary in high regard.

I'm now curious as to why you even have to bemoan that forte has two syllables. Do some folks pronounce it with one, and if so, how does it sound?

JimSpath
Active Contributor
2,410

When I learned the word "forte" for expertise, not the musical phrase, it was pronounced with the 'e' silent. That was a few decades ago. Now I rarely hear that. 

https://www.dictionary.com/browse/forte

Can't argue with your dislike of a dictionary. I found the capture of language to be accurate, given in practice kudo is now a word.

Motto: https://www.goodreads.com/quotes/550389-when-i-use-a-word-it-means-just-what-i

 

qmacro
Developer Advocate
Developer Advocate
0 Kudos
2,381

(I do enjoy these word discussions). Forte is (for me) both expertise and a musical direction, with the same root (strong (-> strength), loud) - I don't see a distinction. I always think of the French accented pronunciation which has the final t (and silent last e) as just enough sound to be a second syllable.

And no, despite what you might claim, kudo is not a word. At least not in my household 🙂

JimSpath
Active Contributor
0 Kudos
2,099

Link above describes kudo evolving (hint: spell check likes just fine): "By the 1920s it began to appear as a plural, and about 25 years later kudo began to appear"

My $5 Unabridged dictionary shows the Greek roots:

Websters New Twentieth CenturyWebsters New Twentieth CenturyDictionary, Websters: KudosDictionary, Websters: Kudos

I applaud the applause (singular or plural). Famous is not the plural of fame, for sure.

<humour></humor>

M-K
Active Participant
2,710

Here's my submission:

MK_0-1722082658566.png

 That Key-as-Segment URL Syntax is interesting, and it can be combined with the parentheses-style in the same URL.

MK_3-1722084161522.png

 

 

 

sachin_sap
Explorer
2,668

Amazing even this kind of circular references work with ease 

/odata/v4/northbreeze/Suppliers(1)?$expand=Products($expand=Category,Supplier($expand=Products($expand=Supplier)))

qmacro
Developer Advocate
Developer Advocate
0 Kudos
2,520

Pretty cool, eh?

sandeepGottipati
Explorer
2,544

sandeepGottipati_0-1722210294178.png

done with task-8

ManojKumarVarma
Explorer
2,353

Hello,

Here is my Submission for Task 8.

ManojKumarVarma_0-1722258888269.png

ManojKumarVarma_1-1722258917775.png


Thanks,

Manoj Kumar Potharaju.

tobiasz_h
Active Participant
2,289

Hello,
My submission for the task 8:

tobiasz_h_0-1722278898640.png

 

spassaro
Participant
2,220

This was quite for free wasn'it?

 

spassaro_0-1722287676100.png

gave me the time to try the "key-as-a-segment" feature (which is definetely for free too :)). I guess is something related with the v4 protocol? 

 

 

qmacro
Developer Advocate
Developer Advocate
1,850

Yes, that was the point (for free) - you'd all worked quite hard on the previous task 😉

And to your Q on the key-as-segment, the answer is yes - see the hyperlink in the main task description and where it takes you 🙂