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 - SAP Cloud Application Programming Model (Week 4)

nicoschoenteich
Employee
Employee

Please note that this challenge is closed. The deadline for receiving a badge upon successful completion has passed. Check out this new challenge for the month of August.

Welcome to the fourth and final week of this month's SAP Developer Challenge. This week we are going to learn about consuming remote services with the SAP Cloud Application Programming Model.

If you haven't read the announcement blog post for this challenge, please head over and do so. This week's challenge builds on top of previous three challenges, which you should have completed before starting with this one.

The Challenge

We have already come a long way with our application since week 1 of the challenge. We have a solid data model, load initial data and can track golf rounds, but still there is one central component missing - the golf players. Wouldn't it be nice to track who played a round of golf? The simplest approach here would be to create a new entity in our data model, but I think we should use this as an opportunity to learn how to consume remote services. The remote service that we are going to consume exposes the API of this SAP Community Groups platform, because the players will be you folks! We will integrate an remote service that lists everyone who completed week 1 of this challenge successfully, and these community members will be the "golf players".

This is what you have to do to successfully complete this week's challenge:

1. Check out the service that we are going to consume: https://developer-advocates-free-tier-central-hana-cloud-instan3abe9a0e.cfapps.us10.hana.ondemand.co...

2. Copy the following metadata information from the remote service into a new file RemoteService.edmx in the root of your project. CAP will need this information to know how to integrate the remote service:

 

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
    <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml">
        <edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/>
    </edmx:Reference>
    <edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Common.xml">
        <edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1"/>
    </edmx:Reference>
    <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
        <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1"/>
    </edmx:Reference>
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="CatalogService">
            <EntityContainer Name="EntityContainer">
                <EntitySet Name="Players" EntityType="CatalogService.Players"/>
            </EntityContainer>
            <EntityType Name="Players">
                <Key>
                    <PropertyRef Name="name"/>
                </Key>
                <Property Name="name" Type="Edm.String" Nullable="false"/>
            </EntityType>
            <Annotations Target="CatalogService.EntityContainer/Players">
                <Annotation Term="Capabilities.DeleteRestrictions">
                    <Record Type="Capabilities.DeleteRestrictionsType">
                        <PropertyValue Property="Deletable" Bool="false"/>
                    </Record>
                </Annotation>
                <Annotation Term="Capabilities.InsertRestrictions">
                    <Record Type="Capabilities.InsertRestrictionsType">
                        <PropertyValue Property="Insertable" Bool="false"/>
                    </Record>
                </Annotation>
                <Annotation Term="Capabilities.UpdateRestrictions">
                    <Record Type="Capabilities.UpdateRestrictionsType">
                        <PropertyValue Property="Updatable" Bool="false"/>
                    </Record>
                </Annotation>
            </Annotations>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

 

3. We can now properly import this metadata into our project (CDS import API) by running the following command from the root of our project: cds import RemoteService.edmx 

4. Explore the newly generated srv/external/ directory. It contains the previously used edmx file as well as a newly generated Schema Notation (CSN) file, which is a "notation for compact representations of CDS models".

5. Inspect the changes that were made to the package.json. There was a new cds.requires.RemoteService section added to make CDS aware of the remote service we imported and are about to use in the next steps.

6.  Add a new file .env  (don't forget the leading dot) to the project root. This file is usually used to define environment variables that will automatically get picked up by CDS. Although we will not store real credentials in this file (or anywhere else in this project), this file would be a good place to do that. It is important to never commit this file to any source code control system (like git).

7. Add the following code to the newly created .env, which adds the service url as "credentials" to the remote service definition:

 

cds.requires.RemoteService.credentials.url=https://developer-advocates-free-tier-central-hana-cloud-instan3abe9a0e.cfapps.us10.hana.ondemand.com/browse/

 

8. Replace the content of the srv/cat-service.cds with the following code. This service definition uses the remote service (line 2) and integrates its "Players" entity into our CatalogService (line 5):

 

using { golf } from '../db/schema';
using { RemoteService as external } from './external/RemoteService';

service CatalogService @(path:'/browse') {
  entity Players as projection on external.Players;
  entity Rounds as projection on golf.Rounds;
  entity Holes as projection on golf.Holes;
  entity Shots as projection on golf.Shots;
}

 

9. Add the following code to the main exported function of the srv/cat-service.js, which is our service handler file from last week. This code makes sure that all incoming request to the "Players" entity will in fact get forwarded to the RemoteService:

 

const remote = await cds.connect.to('RemoteService')
this.on('*', 'Players', (req) => {
    console.log('>> delegating to remote service...')
    return remote.run(req.query)
})

 

10. Start the cds server like usual and inspect the console output. You should see that CDS is connecting to the url of the RemoteService.

11. Share a screen shot of the CatalogService running on your localhost and exposing the remote "Players" entity with its data. It should look something like this:

2023-07-26_11-30-35.png

Resources

We have gathered a few helpful resources for this week's challenge. Feel free to use the comments sections if you have question or need help.

Further Learning

As this week marks the end of this SAP Developer Challenge, here is some inspiration for how you could further improve the application:

 

We hope you enjoyed this SAP Developer Challenge and learned something new. Feel free to share feedback and your experience in the comment section down below or via a private message!

Good luck and happy learning!

101 REPLIES 101

Geeth
Employee
Employee

Hi Nicolai,

Please find the screenshot attached.

Geeth_0-1690371308475.png

 

Well done βœ…

TRuloff
Galactic 2
Galactic 2

Cool idea with the Players service!

cap-dev-challenge-4.png

0 Kudos

Well done βœ…

thomas_jung
Employee
Employee
0 Kudos

My entry for week 4
2023-07-26_08-23-08.png

I've built this out a little further integrating the external service into the main data model. 
2023-07-26_09-13-25.png

And in a Fiori UI from annotations - the external service is feeding the value help
2023-07-26_09-18-12.png

0 Kudos

You r a BOSS....

0 Kudos

Hello Thomas, just curious why did u chose to have a composition between rounds and players. Players can exist outside of rounds isn't it ??

It isn't a composition of players (the external entity). It's a composition of the assignment of players to rounds, which in turn has an association to the player external entity. So, players absolutely exist outside the scope of the rounds.  But you can only assign one or more valid players to a round. 
https://github.com/jung-thomas/cap-dev-challenge-july-2023/blob/ab035bb5844e4de9b3a9d284bf3f7ca31467...

thomas_jung_0-1690396107290.png

 

0 Kudos

Thank you for the response.  Just a follow-up how is it different to use aspect vs entity for the Round2People. is there a difference while generating the DDL

There is a difference - the Round2People doesn't get generated as a standalone entity at the service layer. It's like it's expanded in place. Also the Up__ID and backlink association gets generated by the compiler as well. You are letting CAP take care of more of the relationship definition for you. 

Read more about Composition of Aspects here:
Domain Modeling | CAPire (cloud.sap)

Definition Language (CDL) | CAPire (cloud.sap)

Short summary from the Docu -

Managed Compositions are mostly syntactical sugar: Behind the scenes, they are unfolded to the unmanaged equivalent

0 Kudos

Thank you, that was helpful. Read the documentation previously but could never user it. now that you have displayed the use case could related to it. 

0 Kudos

I was trying this and added the aspect as you shown above. 

dhegde_0-1690613737101.png

However, VS code shows this error while adding LineItem Rerference facet on Rounds object page

dhegde_1-1690613765981.png

Neverthelss, it does work.  But I could not wrap my head around it.  My intution was to do something like this - Add LineItem annotation to Players entity from CatalogService

dhegde_2-1690613857816.png

and then refer to this from Rounds as below (and code completion also shows this as such, and no error too)

dhegde_3-1690613898752.png

But it throws the error :

dhegde_4-1690613920927.png

what am I missing? could you please explain?  Thank you.

I get the same syntax error from the Linter.  But this is the correct syntax.  I think it's just the linter being behind what is possible with CAP.  The aspect based composition is a relatively new-ish feature. 

0 Kudos

ah! OK. Makes sense.  Thank you for the response.  

0 Kudos

Nice trick with the "proxy entity" πŸ‘πŸΌ

0 Kudos

Thanks for sharing knowledges and be the leader for us.

romi9035
Galactic 2
Galactic 2

My submission Week 4:

romil_agrawal_1-1690374528356.png

 

 

0 Kudos

Well done βœ…

antothomasraja
Galactic 1
Galactic 1

Hi @nicoschoenteich 

Below is my submission for week 4,

antothomasraja_0-1690382670182.png

Thank you! Happy Learning πŸ™‚

Best Regards,

Anto

0 Kudos

Well done βœ…

steph_senita
Galactic 2
Galactic 2

Hi @nicoschoenteich 

Below is my submission for this week.

steph_senita_0-1690383620169.png

0 Kudos

Well done βœ…

P41l
Galactic 2
Galactic 2

Here are my results for this week's exercise.

P41l_0-1690384632296.png

 

0 Kudos

Well done βœ…

sabarna17
Galactic 3
Galactic 3

Awesome learning experience in SAP CAP(🧒). Here is the my submission for week 4:
Week4.png

0 Kudos

Well done βœ…

Cmdd
Galactic 3
Galactic 3

Fourth week submission πŸ™‚

Cmdd_0-1690386972744.png

 

0 Kudos

Well done βœ…

MadhavKumar
Galactic 3
Galactic 3

Week 4 Submission snapshot-

MadhavKumar_0-1690389552038.png

 

Regards,

Madhav Kumar

0 Kudos

Well done βœ…

geek
Galactic 3
Galactic 3

I know it's not pretty:

geek_0-1690391705647.png

 

0 Kudos

That works, well done βœ…

ajos
Galactic 3
Galactic 3

My submission

 

ajos_0-1690395789163.png

 

0 Kudos

Well done βœ…

cguttikonda24
Galactic 3
Galactic 3

@nicoschoenteich My week 4 submission.

cguttikonda24_0-1690395834476.png

 

0 Kudos

Well done βœ…

alessandraarm
Galactic 3
Galactic 3

Hello!

Here my submission for this week (the last one... πŸ˜’)

alessandraarm_0-1690398133973.png

I really loved this challenge using service (and also because my user is in all screen shots πŸ˜…)!!

Thanks for every week support!

0 Kudos

Well done, I'm glad you enjoyed the challenge βœ…