├── .github └── ISSUE_TEMPLATE │ └── session-feedback-template.md ├── .gitignore ├── .reuse └── dep5 ├── LICENSES └── Apache-2.0.txt ├── README.md └── exercises ├── 01_java_setting_up_bas_dev_environment.md ├── 01_node_setting_up_bas_dev_environment.md ├── 02_java_introduction_to_incident_management_application.md ├── 02_node_introduction_to_incident_management_application.md ├── 03_java_domain_modeling.md ├── 03_node_domain_modeling.md ├── 04_java_creating_services.md ├── 04_node_creating_services.md ├── 05_java_adding_data.md ├── 05_node_adding_data.md ├── 06_java_adding_fiori_elements.md ├── 06_node_adding_fiori_elements.md ├── 07_java_adding_authorization.md ├── 07_node_adding_authorization.md ├── 08_java_optional_add_multitenancy.md ├── 08_node_optional_add_multitenancy.md └── assets ├── Terminal.png ├── create_dev_space.png ├── create_space.png ├── data_source.png ├── data_source_java.png ├── domain.drawio.svg ├── entity_selection.png ├── entity_selection_java.png ├── full_stack_application.png ├── incidents_mgmt.png ├── incidents_mgmt_java.png ├── java_auto_build.png ├── java_auto_save.png ├── mtx.png ├── open_folder.png ├── project_attributes.png ├── project_attributes_java.png ├── services.png ├── services_java.png ├── spaces.png └── template_selection.png /.github/ISSUE_TEMPLATE/session-feedback-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Session Feedback Template 3 | about: To give feedback on the session 4 | title: Session Feedback 5 | labels: feedback 6 | assignees: '' 7 | 8 | --- 9 | 10 | Thanks for taking a couple of minutes to give feedback, which will help me improve for next time. 11 | 12 | **Instructions** 13 | 1. Before doing anything else, hit the green button "Submit new issue" right now to save this issue content 14 | 1. Then go through the questions and mark a single checkbox for each, to represent your answer 15 | 1. Finally, in the empty comment box below this one, please describe what you liked and what you didn't like 16 | 17 | **What was your experience of before this session?** 18 | - [ ] Not much at all 19 | - [ ] Basic knowledge 20 | - [ ] Used it now and then 21 | - [ ] Regular user 22 | 23 | **Did this session meet your expectations?** 24 | - [ ] Not really 25 | - [ ] Somewhat 26 | - [ ] Mostly 27 | 28 | **Was the time allotted to each exercise enough for you to work through them?** 29 | - [ ] Not really 30 | - [ ] On the whole, yes 31 | 32 | **How did you find the actual individual (👉) tasks in the exercises?** 33 | - [ ] Not relevant enough 34 | - [ ] Hard to do 35 | - [ ] About right 36 | - [ ] Helpful / informative 37 | 38 | **How would you relate yourself to thie topic ?** 39 | - [ ] I use these concepts day to day 40 | - [ ] I might work on this soon 41 | - [ ] I came to learn, I wont be working on this. 42 | 43 | **How was your experience with interface?** 44 | - [ ] Easy to use and understand 45 | - [ ] Needs time to get a hang of it 46 | - [ ] Not intuitive 47 | - [ ] Extermly Unusable 48 | 49 | If you have time, please add a comment below to write free-form what you liked and what you disliked about the session. Thanks! -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: dcom2023-template 3 | Upstream-Contact: () 4 | Source: https://github.com/sap-samples/dkom2021-template 5 | Disclaimer: The code in this project may include calls to APIs (“API Calls”) of 6 | SAP or third-party products or services developed outside of this project 7 | (“External Products”). 8 | “APIs” means application programming interfaces, as well as their respective 9 | specifications and implementing code that allows software to communicate with 10 | other software. 11 | API Calls to External Products are not licensed under the open source license 12 | that governs this project. The use of such API Calls and related External 13 | Products are subject to applicable additional agreements with the relevant 14 | provider of the External Products. In no event shall the open source license 15 | that governs this project grant any rights in or to any External Products,or 16 | alter, expand or supersede any terms of the applicable additional agreements. 17 | If you have a valid license agreement with SAP for the use of a particular SAP 18 | External Product, then you may make use of any API Calls included in this 19 | project’s code for that SAP External Product, subject to the terms of such 20 | license agreement. If you do not have a valid license agreement for the use of 21 | a particular SAP External Product, then you may only make use of any API Calls 22 | in this project for that SAP External Product for your internal, non-productive 23 | and non-commercial test and evaluation of such API Calls. Nothing herein grants 24 | you any rights to use or access any SAP External Product, or provide any third 25 | parties the right to use of access any SAP External Product, through API Calls. 26 | 27 | Files: * 28 | Copyright: 2022 SAP SE or an SAP affiliate company and dcom2023-template contributors 29 | License: Apache-2.0 30 | -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, 6 | AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | 11 | 12 | "License" shall mean the terms and conditions for use, reproduction, and distribution 13 | as defined by Sections 1 through 9 of this document. 14 | 15 | 16 | 17 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 18 | owner that is granting the License. 19 | 20 | 21 | 22 | "Legal Entity" shall mean the union of the acting entity and all other entities 23 | that control, are controlled by, or are under common control with that entity. 24 | For the purposes of this definition, "control" means (i) the power, direct 25 | or indirect, to cause the direction or management of such entity, whether 26 | by contract or otherwise, or (ii) ownership of fifty percent (50%) or more 27 | of the outstanding shares, or (iii) beneficial ownership of such entity. 28 | 29 | 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions 32 | granted by this License. 33 | 34 | 35 | 36 | "Source" form shall mean the preferred form for making modifications, including 37 | but not limited to software source code, documentation source, and configuration 38 | files. 39 | 40 | 41 | 42 | "Object" form shall mean any form resulting from mechanical transformation 43 | or translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, and conversions to other media types. 45 | 46 | 47 | 48 | "Work" shall mean the work of authorship, whether in Source or Object form, 49 | made available under the License, as indicated by a copyright notice that 50 | is included in or attached to the work (an example is provided in the Appendix 51 | below). 52 | 53 | 54 | 55 | "Derivative Works" shall mean any work, whether in Source or Object form, 56 | that is based on (or derived from) the Work and for which the editorial revisions, 57 | annotations, elaborations, or other modifications represent, as a whole, an 58 | original work of authorship. For the purposes of this License, Derivative 59 | Works shall not include works that remain separable from, or merely link (or 60 | bind by name) to the interfaces of, the Work and Derivative Works thereof. 61 | 62 | 63 | 64 | "Contribution" shall mean any work of authorship, including the original version 65 | of the Work and any modifications or additions to that Work or Derivative 66 | Works thereof, that is intentionally submitted to Licensor for inclusion in 67 | the Work by the copyright owner or by an individual or Legal Entity authorized 68 | to submit on behalf of the copyright owner. For the purposes of this definition, 69 | "submitted" means any form of electronic, verbal, or written communication 70 | sent to the Licensor or its representatives, including but not limited to 71 | communication on electronic mailing lists, source code control systems, and 72 | issue tracking systems that are managed by, or on behalf of, the Licensor 73 | for the purpose of discussing and improving the Work, but excluding communication 74 | that is conspicuously marked or otherwise designated in writing by the copyright 75 | owner as "Not a Contribution." 76 | 77 | 78 | 79 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 80 | of whom a Contribution has been received by Licensor and subsequently incorporated 81 | within the Work. 82 | 83 | 2. Grant of Copyright License. Subject to the terms and conditions of this 84 | License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 85 | no-charge, royalty-free, irrevocable copyright license to reproduce, prepare 86 | Derivative Works of, publicly display, publicly perform, sublicense, and distribute 87 | the Work and such Derivative Works in Source or Object form. 88 | 89 | 3. Grant of Patent License. Subject to the terms and conditions of this License, 90 | each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 91 | no-charge, royalty-free, irrevocable (except as stated in this section) patent 92 | license to make, have made, use, offer to sell, sell, import, and otherwise 93 | transfer the Work, where such license applies only to those patent claims 94 | licensable by such Contributor that are necessarily infringed by their Contribution(s) 95 | alone or by combination of their Contribution(s) with the Work to which such 96 | Contribution(s) was submitted. If You institute patent litigation against 97 | any entity (including a cross-claim or counterclaim in a lawsuit) alleging 98 | that the Work or a Contribution incorporated within the Work constitutes direct 99 | or contributory patent infringement, then any patent licenses granted to You 100 | under this License for that Work shall terminate as of the date such litigation 101 | is filed. 102 | 103 | 4. Redistribution. You may reproduce and distribute copies of the Work or 104 | Derivative Works thereof in any medium, with or without modifications, and 105 | in Source or Object form, provided that You meet the following conditions: 106 | 107 | (a) You must give any other recipients of the Work or Derivative Works a copy 108 | of this License; and 109 | 110 | (b) You must cause any modified files to carry prominent notices stating that 111 | You changed the files; and 112 | 113 | (c) You must retain, in the Source form of any Derivative Works that You distribute, 114 | all copyright, patent, trademark, and attribution notices from the Source 115 | form of the Work, excluding those notices that do not pertain to any part 116 | of the Derivative Works; and 117 | 118 | (d) If the Work includes a "NOTICE" text file as part of its distribution, 119 | then any Derivative Works that You distribute must include a readable copy 120 | of the attribution notices contained within such NOTICE file, excluding those 121 | notices that do not pertain to any part of the Derivative Works, in at least 122 | one of the following places: within a NOTICE text file distributed as part 123 | of the Derivative Works; within the Source form or documentation, if provided 124 | along with the Derivative Works; or, within a display generated by the Derivative 125 | Works, if and wherever such third-party notices normally appear. The contents 126 | of the NOTICE file are for informational purposes only and do not modify the 127 | License. You may add Your own attribution notices within Derivative Works 128 | that You distribute, alongside or as an addendum to the NOTICE text from the 129 | Work, provided that such additional attribution notices cannot be construed 130 | as modifying the License. 131 | 132 | You may add Your own copyright statement to Your modifications and may provide 133 | additional or different license terms and conditions for use, reproduction, 134 | or distribution of Your modifications, or for any such Derivative Works as 135 | a whole, provided Your use, reproduction, and distribution of the Work otherwise 136 | complies with the conditions stated in this License. 137 | 138 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 139 | Contribution intentionally submitted for inclusion in the Work by You to the 140 | Licensor shall be under the terms and conditions of this License, without 141 | any additional terms or conditions. Notwithstanding the above, nothing herein 142 | shall supersede or modify the terms of any separate license agreement you 143 | may have executed with Licensor regarding such Contributions. 144 | 145 | 6. Trademarks. This License does not grant permission to use the trade names, 146 | trademarks, service marks, or product names of the Licensor, except as required 147 | for reasonable and customary use in describing the origin of the Work and 148 | reproducing the content of the NOTICE file. 149 | 150 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to 151 | in writing, Licensor provides the Work (and each Contributor provides its 152 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 153 | KIND, either express or implied, including, without limitation, any warranties 154 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR 155 | A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness 156 | of using or redistributing the Work and assume any risks associated with Your 157 | exercise of permissions under this License. 158 | 159 | 8. Limitation of Liability. In no event and under no legal theory, whether 160 | in tort (including negligence), contract, or otherwise, unless required by 161 | applicable law (such as deliberate and grossly negligent acts) or agreed to 162 | in writing, shall any Contributor be liable to You for damages, including 163 | any direct, indirect, special, incidental, or consequential damages of any 164 | character arising as a result of this License or out of the use or inability 165 | to use the Work (including but not limited to damages for loss of goodwill, 166 | work stoppage, computer failure or malfunction, or any and all other commercial 167 | damages or losses), even if such Contributor has been advised of the possibility 168 | of such damages. 169 | 170 | 9. Accepting Warranty or Additional Liability. While redistributing the Work 171 | or Derivative Works thereof, You may choose to offer, and charge a fee for, 172 | acceptance of support, warranty, indemnity, or other liability obligations 173 | and/or rights consistent with this License. However, in accepting such obligations, 174 | You may act only on Your own behalf and on Your sole responsibility, not on 175 | behalf of any other Contributor, and only if You agree to indemnify, defend, 176 | and hold each Contributor harmless for any liability incurred by, or claims 177 | asserted against, such Contributor by reason of your accepting any such warranty 178 | or additional liability. END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following boilerplate 183 | notice, with the fields enclosed by brackets "[]" replaced with your own identifying 184 | information. (Don't include the brackets!) The text should be enclosed in 185 | the appropriate comment syntax for the file format. We also recommend that 186 | a file or class name and description of purpose be included on the same "printed 187 | page" as the copyright notice for easier identification within third-party 188 | archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | 194 | you may not use this file except in compliance with the License. 195 | 196 | You may obtain a copy of the License at 197 | 198 | http://www.apache.org/licenses/LICENSE-2.0 199 | 200 | Unless required by applicable law or agreed to in writing, software 201 | 202 | distributed under the License is distributed on an "AS IS" BASIS, 203 | 204 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 205 | 206 | See the License for the specific language governing permissions and 207 | 208 | limitations under the License. 209 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HO003 - Getting started with CAP 2 | 3 | ## Description 4 | 5 | In this hands-on tutorial you will learn to create your first CAP application. It will be a very basic, yet fully functional application including a Fiori Elements UI. 6 | 7 | ## Prerequisite 8 | 9 | - A internet browser. Preferrably Google Chrome. 10 | 11 | ## Exercises 12 | 13 | **Hint:** CAP has 2 runtime stacks: CAP Java and CAP node.js 14 | 15 | For this tutorial we describe the steps for both stacks. You're invited to test both. In a real world project you need to decide for one stack based on your team's skillset and the (non-functional) requirements of your project. 16 | 17 | ### CAP Java 18 | 19 | 1. [Setting up BAS development environment](exercises/01_java_setting_up_bas_dev_environment.md) 20 | 2. [Introduction to the Incident Management application](exercises/02_java_introduction_to_incident_management_application.md) 21 | 3. [Domain Modeling](exercises/03_java_domain_modeling.md) 22 | 4. [Creating services](exercises/04_java_creating_services.md) 23 | 5. [Adding data](exercises/05_java_adding_data.md) 24 | 6. [Adding Fiori Elements UI](exercises/06_java_adding_fiori_elements.md) 25 | 7. [Adding authorization](exercises/07_java_adding_authorization.md) 26 | 27 | ### CAP node.js 28 | 29 | 1. [Setting up BAS development environment](exercises/01_node_setting_up_bas_dev_environment.md) 30 | 2. [Introduction to the Incident Management application](exercises/02_node_introduction_to_incident_management_application.md) 31 | 3. [Domain Modeling](exercises/03_node_domain_modeling.md) 32 | 4. [Creating services](exercises/04_node_creating_services.md) 33 | 5. [Adding data](exercises/05_node_adding_data.md) 34 | 6. [Adding Fiori Elements UI](exercises/06_node_adding_fiori_elements.md) 35 | 7. [Adding authorization](exercises/07_node_adding_authorization.md) 36 | 8. [Otional: Adding Multitenancy](exercises/08_node_optional_add_multitenancy.md) 37 | 38 | 39 | 42 | 43 | ## License 44 | 45 | Copyright (c) 2022 SAP SE or an SAP affiliate company. All rights reserved. This project is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSES/Apache-2.0.txt) file. 46 | -------------------------------------------------------------------------------- /exercises/01_java_setting_up_bas_dev_environment.md: -------------------------------------------------------------------------------- 1 | # Setting up Dev Environment 2 | 1. For SAP internal users (inside SAP network) you can use the following link to accesss BAS: https://go.sap.corp/bas_cap 3 | 4 | 5 | 2. All others can use the [Business Application Studio](https://lcapteched.eu10cf.applicationstudio.cloud.sap/index.html) -> open this page in a new browser tab. For the login you'll need credentials that you can generate [here](https://cap-enablement-team.launchpad.cfapps.eu12.hana.ondemand.com/a6f9aec4-7c3b-4059-a3b6-4b66229a7926.sapfecapcredentials.credentialsservice-0.0.1/index.html) -> open this page in a new browser tab. Retrieve a user by clicking the `Get fresh credentials` button. 6 | 7 | 3. Once logged in, click on `Create Dev Space` 8 |
9 | 10 | ![Create Dev Space](./assets/create_dev_space.png) 11 |
12 | 13 | 4. You will be redirected to choose what kind of application you want to create and to choose the name of the dev space. Here, you can name the dev space as `incidents_mgmt` and choose `Full Stack Cloud Application` 14 |
15 | 16 | ![Full Stack Cloud Application](./assets/full_stack_application.png) 17 |
18 | 19 | 5. Click on `Create Dev Space` 20 |
21 | 22 | ![Create Dev Space](./assets/create_space.png) 23 |
24 | 25 | 6. Wait for the dev space to start, once it has started running, you can open it. 26 |
27 | 28 | ![Open Space](./assets/spaces.png) 29 |
30 | 31 | 7. Once your space is opened you need to perform a small adjustment to the settings in order to have a smooth developer experience while developing your CAP Java application. Click the cog-wheel in the bottom left corner and then click "settings". Perform the following 2 steps. 32 |
33 | 34 | 8. At first you need to *enable* "autobuild" for Java artifacts. This is needed to have quick turnarounds with Spring Boot DevTools while using `mvn cds:watch`. 35 |
36 | 37 | ![enable Java autobuild](./assets/java_auto_build.png) 38 | 39 |
40 | 41 | 9. Then, you need to *disable* "auto save". This prevents that an automatic, yet incremental, build is triggered after each key-stroke. ;-) 42 | 43 | ![disable auto save](./assets/java_auto_save.png) 44 | 45 | 10. Your space is ready for use. You can open the terminal by clicking on the top left button and then `Terminal -> New Terminal` 46 |
47 | 48 | ![Open Terminal](./assets/Terminal.png) 49 | 50 | *** 51 | 52 | Proceed with the next step: [Introduction to the Incident Management application](02_java_introduction_to_incident_management_application.md) 53 | -------------------------------------------------------------------------------- /exercises/01_node_setting_up_bas_dev_environment.md: -------------------------------------------------------------------------------- 1 | # Setting up Dev Environment 2 | 3 | 1. For SAP internal users (inside SAP network) you can use the following link to accesss BAS: https://go.sap.corp/bas_cap 4 | 5 | 6 | 2. All others can use the [Business Application Studio](https://lcapteched.eu10cf.applicationstudio.cloud.sap/index.html) -> open this page in a new browser tab. For the login you'll need credentials that you can generate [here](https://cap-enablement-team.launchpad.cfapps.eu12.hana.ondemand.com/a6f9aec4-7c3b-4059-a3b6-4b66229a7926.sapfecapcredentials.credentialsservice-0.0.1/index.html) -> open this page in a new browser tab. Retrieve a user by clicking the `Get fresh credentials` button. 7 | 8 | 3. Once logged in, click on `Create Dev Space` 9 |
10 | 11 | ![Create Dev Space](./assets/create_dev_space.png) 12 |
13 | 14 | 4. You will be redirected to choose what kind of application you want to create and to choose the name of the dev space. 15 |
16 | 17 | Here, you can name the dev space as `incidents_mgmt` and choose `Full Stack Cloud Application` 18 |
19 | 20 | ![Full Stack Cloud Application](./assets/full_stack_application.png) 21 |
22 | 23 | 5. Click on `Create Dev Space` 24 |
25 | 26 | ![Create Dev Space](./assets/create_space.png) 27 |
28 | 29 | 6. Wait for the dev space to start, once it has started running, you can open it. 30 |
31 | 32 | ![Open Space](./assets/spaces.png) 33 |
34 | 35 | 7. Your space is ready for use. You can open the terminal by clicking on the top left button and then `Terminal -> New Terminal` 36 |
37 | 38 | ![Open Terminal](./assets/Terminal.png) 39 | 40 | *** 41 | 42 | Proceed with the next step: [Introduction to the Incident Management application](02_node_introduction_to_incident_management_application.md) 43 | -------------------------------------------------------------------------------- /exercises/02_java_introduction_to_incident_management_application.md: -------------------------------------------------------------------------------- 1 | # Incident Management Application 2 | 3 | In this exercise we assume we are a developer given the task to implement an application to create and manage incidents, that is customer support messages. 4 | The application will allow customers to create incidents, processed by support team members. Both add comments to a conversation. Eventually, a repair appointment is created with a service worker assigned. 5 | 6 | ## Create a new project 7 | 8 | To create a new CAP project, you can use the `cds init` command. This command creates the needed project configuration for you to start developing your application. Since this exercise is about creating a simple incident management application, the project name will be `incidents`. 9 | 10 | Use the following command in the terminal: 11 | ```sh 12 | cds init incidents --add java 13 | ``` 14 | 15 | ## Load the project in the editor 16 | 17 | Now, it's time to load our IDE and access the newly created directory. 18 | You can open the project folder `incidents` in your choice of IDE 19 | 20 | In BAS: 21 | 22 | 1. Go to `Explorer -> Open Folder` 23 |
24 | 25 | ![Open Folder](./assets/open_folder.png) 26 |
27 | 28 | 2. Choose `incidents` from the file explorer. 29 |
30 | 31 | ![Open Application](./assets/incidents_mgmt_java.png) 32 |
33 | 34 | Basic CAP structure containing folder `db` and `srv` has been created. 35 | 36 | For now, the CAP Java application cannot serve any purpose as it has neither defined a domain model nor a service interface. This will be done in the following steps. 37 | 38 | 39 | *** 40 | 41 | Proceed with the next step: [Domain modeling](03_java_domain_modeling.md) 42 | -------------------------------------------------------------------------------- /exercises/02_node_introduction_to_incident_management_application.md: -------------------------------------------------------------------------------- 1 | # Incident Management Application 2 | 3 | In this exercise we assume we are a developer given the task to implement an application to create and manage incidents, that is customer support messages. 4 | The application will allow customers to create incidents, processed by support team members. Both add comments to a conversation. Eventually, a repair appointment is created with a service worker assigned. 5 | 6 | ## Create a new project 7 | 8 | To create a new CAP project, you can use the `cds init` command. This command creates the needed project configuration for you to start developing your application. Since this exercise is about creating a simple incident management application, the project name will be `incidents-mgmt`. 9 | 10 | Use the following command in the terminal: 11 | ```sh 12 | cds init incidents-mgmt 13 | ``` 14 | 15 | ## Load the project in the editor 16 | 17 | Now, it's time to load our IDE and access the newly created directory. 18 | You can open the project folder `incidents-mgmt` in your choice of IDE 19 | 20 | In BAS: 21 | 22 | 1. Go to `Explorer -> Open Folder` 23 |
24 | 25 | ![Open Folder](./assets/open_folder.png) 26 |
27 | 28 | 2. Choose `incidents-mgmt` from the file explorer. 29 |
30 | 31 | ![Open Application](./assets/incidents_mgmt.png) 32 |
33 | 34 | Basic CAP structure containing folder `app`, `db` and `srv` has been created. 35 | 36 | Open the terminal and use the command: 37 | ```sh 38 | npm install 39 | ``` 40 | to install the dependencies. 41 | 42 | Start the CAP server by using `cds watch` in the Integrated Terminal. 43 | 44 | ```sh 45 | cds watch 46 | ``` 47 | The CAP server serves all the CAP sources from your project. It also "watches" all the files in your projects and conveniently restarts whenever you save a file. Changes you have made will immediately be served without you having to do anything. 48 |
49 | 50 | Currently, it will show 51 | 52 | `No service definitions found in loaded models...` 53 |
54 | 55 | It tells you that there is no model and no service definitions yet that it can serve. 56 |
57 | 58 | We will be adding the service definitions in the upcoming modules. 59 | 60 | *** 61 | 62 | Proceed with the next step: [Domain modeling](03_node_domain_modeling.md) -------------------------------------------------------------------------------- /exercises/03_java_domain_modeling.md: -------------------------------------------------------------------------------- 1 | # Domain Modeling 2 | 3 | The conceptual domain model for our incidents management application is as follows: 4 | 5 | - Customers can create Incidents (either directly or via agents) 6 | - Incidents have a title and a Conversation of several Messages 7 | - Incidents are resolved through repairs, kept track of as scheduled Appointments of available Service Workers 8 | 9 |

10 | 11 | ![Domain model](./assets/domain.drawio.svg) 12 | 13 |
14 | 15 | ## Steps: 16 | 1. Create a file `schema.cds` in `db` folder of the project. 17 | 2. Copy the following content in the file: 18 | 19 | ```cds 20 | using { cuid, managed, sap.common.CodeList } from '@sap/cds/common'; 21 | namespace sap.capire.incidents; 22 | 23 | /** 24 | * Customers using products sold by our company. 25 | * Customers can create support Incidents. 26 | */ 27 | entity Customers : cuid, managed { 28 | firstName : String; 29 | lastName : String; 30 | email : EMailAddress; 31 | phone : PhoneNumber; 32 | city : City; 33 | postCode : String; 34 | streetAddress : String; 35 | incidents : Composition of many Incidents on incidents.customer = $self; 36 | } 37 | 38 | /** 39 | * Incidents created by Customers. 40 | */ 41 | entity Incidents : cuid, managed { 42 | customer : Association to Customers; 43 | title : String @title : 'Title'; 44 | urgency : Association to Urgency; 45 | status : Association to Status; 46 | conversations: Composition of many Conversations on conversations.incidents = $self; 47 | } 48 | 49 | entity Status : CodeList { 50 | key code: String enum { 51 | new = 'N'; 52 | assigned = 'A'; 53 | in_process = 'I'; 54 | on_hold = 'H'; 55 | resolved = 'R'; 56 | closed = 'C'; 57 | }; 58 | } 59 | 60 | entity Urgency : CodeList { 61 | key code: String enum { 62 | high = 'H'; 63 | medium = 'M'; 64 | low = 'L'; 65 | }; 66 | } 67 | 68 | entity Conversations : cuid, managed { 69 | incidents : Association to Incidents; 70 | timestamp : DateTime; 71 | author : String @cds.on.insert: $user; 72 | message : String; 73 | } 74 | 75 | type EMailAddress : String; 76 | type PhoneNumber : String; 77 | type City : String; 78 | 79 | ``` 80 | 81 |
82 | 83 | Note: You can read more about [Domain Modelling](https://cap.cloud.sap/docs/guides/domain-modeling), [entites](https://cap.cloud.sap/docs/cds/cdl#entities) and [types](https://cap.cloud.sap/docs/cds/cdl#types). 84 |
85 | 86 | As soon as the CDS file is saved, you can start your CAP Java application. Open a terminal (like described above) and run the commands 87 | 88 | ``` 89 | cd srv 90 | mvn cds:watch 91 | ``` 92 | 93 | The `mvn cds:watch` command keeps an eye on your changes (including the CDS files) and triggers a rebuild and restart automatically. 94 | 95 | On the started application you won't be able to see much, yet. There are no definitions for the service interface of your application. You'll create them in the next step. :) 96 | 97 | *** 98 | 99 | Proceed with the next step: [Creating services](04_java_creating_services.md) 100 | -------------------------------------------------------------------------------- /exercises/03_node_domain_modeling.md: -------------------------------------------------------------------------------- 1 | # Domain Modeling 2 | 3 | The conceptual domain model for our incidents management application is as follows: 4 | 5 | - Customers can create Incidents (either directly or via agents) 6 | - Incidents have a title and a Conversation of several Messages 7 | - Incidents are resolved through repairs, kept track of as scheduled Appointments of available Service Workers 8 | 9 |

10 | 11 | ![Domain model](./assets/domain.drawio.svg) 12 | 13 |
14 | 15 | ## Steps: 16 | 1. Create a file `schema.cds` in `db` folder of the project. 17 | 2. Copy the following content in the file: 18 | 19 | ```cds 20 | using { cuid, managed, sap.common.CodeList } from '@sap/cds/common'; 21 | namespace sap.capire.incidents; 22 | 23 | /** 24 | * Customers using products sold by our company. 25 | * Customers can create support Incidents. 26 | */ 27 | entity Customers : cuid, managed { 28 | firstName : String; 29 | lastName : String; 30 | email : EMailAddress; 31 | phone : PhoneNumber; 32 | city : City; 33 | postCode : String; 34 | streetAddress : String; 35 | incidents : Composition of many Incidents on incidents.customer = $self; 36 | } 37 | 38 | /** 39 | * Incidents created by Customers. 40 | */ 41 | entity Incidents : cuid, managed { 42 | customer : Association to Customers; 43 | title : String @title : 'Title'; 44 | urgency : Association to Urgency; 45 | status : Association to Status; 46 | conversations: Composition of many Conversations on conversations.incidents = $self; 47 | } 48 | 49 | entity Status : CodeList { 50 | key code: String enum { 51 | new = 'N'; 52 | assigned = 'A'; 53 | in_process = 'I'; 54 | on_hold = 'H'; 55 | resolved = 'R'; 56 | closed = 'C'; 57 | }; 58 | } 59 | 60 | entity Urgency : CodeList { 61 | key code: String enum { 62 | high = 'H'; 63 | medium = 'M'; 64 | low = 'L'; 65 | }; 66 | } 67 | 68 | entity Conversations : cuid, managed { 69 | incidents : Association to Incidents; 70 | timestamp : DateTime; 71 | author : String @cds.on.insert: $user; 72 | message : String; 73 | } 74 | 75 | type EMailAddress : String; 76 | type PhoneNumber : String; 77 | type City : String; 78 | 79 | ``` 80 | 81 |
82 | 83 | Note: You can read more about [Domain Modelling](https://cap.cloud.sap/docs/guides/domain-modeling), [entites](https://cap.cloud.sap/docs/cds/cdl#entities) and [types](https://cap.cloud.sap/docs/cds/cdl#types). 84 |
85 | 86 | As soon as the CDS file is saved, the running `cds watch` commands reacts immediately with the CDS application and reload of the application takes place. The embedded database of the started application will reflect the schema defined in your CDS file. 87 | 88 | *** 89 | 90 | Proceed with the next step: [Creating services](04_node_creating_services.md) -------------------------------------------------------------------------------- /exercises/04_java_creating_services.md: -------------------------------------------------------------------------------- 1 | # Creating Services 2 | 3 | After defining the model, the running application is still not exposing any service endpoints. 4 | 5 | It's a good practice in CAP to create one service per use case. Hence, we will add two service definitions for the different use cases: 6 | 7 | - A `CustomersService` for customers to create and browse their own incidents. 8 | - An `IncidentsService` for support engineers to process incidents created by customers. 9 | 10 | ## Steps: 11 | 12 | 1. Create a new file `customers-service.cds` in the `srv` folder of your project. 13 | 14 | 2. Copy the following content in the file: 15 | 16 | ```cds 17 | using { sap.capire.incidents as my } from '../db/schema'; 18 | 19 | /** 20 | * Used by Customers to create and browse their Incidents. 21 | */ 22 | service CustomersService { 23 | entity Incidents as projection on my.Incidents { * 24 | } excluding { modifiedBy } where customer.ID = $user; 25 | } 26 | ``` 27 | 28 | 3. Create a new file `incidents-service.cds` in the `srv` folder of your project. 29 | 30 | 4. Copy the following content in the file: 31 | 32 | ```cds 33 | using { sap.capire.incidents as my } from '../db/schema'; 34 | 35 | service IncidentsService { 36 | @odata.draft.enabled 37 | entity Incidents as projection on my.Incidents; 38 | entity Customers as projection on my.Customers; 39 | entity Conversations as projection on my.Conversations; 40 | entity Urgency as projection on my.Urgency; 41 | entity Status as projection on my.Status; 42 | } 43 | ``` 44 | 45 | The application is reloaded, open the url mentioned in the terminal in your browser and you can see the generic index.html page. If you don't find the link in the terminal output, you can also use the "Ports Preview" (press `F1 and type `Ports`) and select port `8080`. 46 |
47 | 48 | ![Endpoints](assets/services_java.png) 49 |
50 | 51 | ## Adding Custom Logic 52 | 53 | You can add custom code to deal with the specific domain logic of your application. 54 | 55 | - Create a new folder `handlers` in the `srv/src/main/java/customer/incidents` folder. 56 | - Create a new file `IncidentUrgencyHandler.java` in that folder and add the following content: 57 | 58 | ```java 59 | package customer.incidents.handlers; 60 | 61 | 62 | import java.util.List; 63 | import java.util.Locale; 64 | 65 | import org.slf4j.Logger; 66 | import org.slf4j.LoggerFactory; 67 | import org.springframework.stereotype.Component; 68 | 69 | import com.sap.cds.services.cds.CqnService; 70 | import com.sap.cds.services.handler.EventHandler; 71 | import com.sap.cds.services.handler.annotations.After; 72 | import com.sap.cds.services.handler.annotations.ServiceName; 73 | 74 | import cds.gen.incidentsservice.Incidents; 75 | import cds.gen.incidentsservice.IncidentsService_; 76 | 77 | @Component 78 | @ServiceName(IncidentsService_.CDS_NAME) 79 | public class IncidentUrgencyHandler implements EventHandler { 80 | 81 | private static final Logger logger = LoggerFactory.getLogger(IncidentUrgencyHandler.class); 82 | @After(event = CqnService.EVENT_READ) 83 | public void ensureHighUrgencyForIncidentsWithUrgentInTitle(List incidents) { 84 | 85 | for (Incidents incident : incidents) { 86 | if (incident.getTitle() != null && 87 | incident.getTitle().toLowerCase(Locale.ENGLISH).contains("urgent") && 88 | incident.getUrgencyCode() == null || !"H".equals(incident.getUrgencyCode())) { 89 | 90 | incident.setUrgencyCode("H"); 91 | logger.info("Adjusted Urgency for incident '{}' to 'HIGH'.", incident.getTitle()); 92 | } 93 | } 94 | } 95 | } 96 | ``` 97 | 98 | **Note:** this is the first (and last;)) time in this tutorial where you create Java code. It might happen that the Java support in BAS fails to correctly pick up the code generated from CDS files and gives some error markers in the inserted Java code. In that case you can try one of the following techniques: 99 | 100 | * Press ctrl+shift+p (the command pallette) and type "Java: Clean Java Lanaguage Server Workspace" 101 | * Press ctrl+shift+p (the command pallette) and type "Java: Force Java Compilation" 102 | 103 | Afterwards the error markers should be gone. If not it's still not a road blocker since the `mvn cds:watch` command does not care about IDE errors. ;) 104 | 105 | In case you still run into issues with this handler (you'll see that in the stack trace of the application log) you can just comment the `@After` annotation in line 24. Then this handler will not be called at runtime. 106 | 107 | You can read more about [Providing Services](https://cap.cloud.sap/docs/guides/providing-services/) 108 | 109 | *** 110 | 111 | Proceed with the next step: [Adding data](05_java_adding_data.md) 112 | -------------------------------------------------------------------------------- /exercises/04_node_creating_services.md: -------------------------------------------------------------------------------- 1 | # Creating Services 2 | 3 | After defining the model, the running application is still not exposing any service endpoints. 4 | 5 | It's a good practice in CAP to create one service per use case. Hence, we will add two service definitions to it for the different use cases: 6 | 7 | - A `CustomersService` for customers to create and browse their own incidents. 8 | - An `IncidentsService` for support engineers to process incidents created by customers. 9 | 10 | ## Steps: 11 | 12 | 1. Create a new file `customers-service.cds` in the `srv` folder of your project. 13 | 14 | 2. Copy the following content in the file: 15 | 16 | ```cds 17 | using { sap.capire.incidents as my } from '../db/schema'; 18 | 19 | /** 20 | * Used by Customers to create and browse their Incidents. 21 | */ 22 | @path : '/customers' 23 | service CustomersService { 24 | entity Incidents as projection on my.Incidents { * 25 | } excluding { modifiedBy } where customer.ID = $user; 26 | } 27 | ``` 28 | 29 | 3. Create a new file `incidents-service.cds` in the `srv` folder of your project. 30 | 31 | 4. Copy the following content in the file: 32 | 33 | ```cds 34 | using { sap.capire.incidents as my } from '../db/schema'; 35 | 36 | @path : '/incidents' 37 | service IncidentsService { 38 | @odata.draft.enabled 39 | entity Incidents as projection on my.Incidents; 40 | entity Customers as projection on my.Customers; 41 | entity Conversations as projection on my.Conversations; 42 | entity Urgency as projection on my.Urgency; 43 | entity Status as projection on my.Status; 44 | } 45 | ``` 46 | 47 | The application is reloaded, open the url mentioned in the terminal in your browser and you can see the generic index.html page: 48 |
49 | 50 | ![Endpoints](assets/services.png) 51 |
52 | 53 | ## Adding Custom Logic 54 | 55 | You can add custom code to deal with the specific domain logic of your application. 56 | 57 | - Create file `incidents-service.js` in `srv` folder and add the following content: 58 | 59 | ```js 60 | const cds = require('@sap/cds') 61 | 62 | class IncidentsService extends cds.ApplicationService { 63 | /** Registering custom event handlers */ 64 | init() { 65 | this.before("UPDATE", "Incidents", (req) => this.onUpdate(req)); 66 | this.after("READ", "Incidents", (data) => this.changeUrgencyDueToSubject(data)); 67 | 68 | return super.init(); 69 | } 70 | 71 | changeUrgencyDueToSubject(data) { 72 | if (data) { 73 | const incidents = Array.isArray(data) ? data : [data]; 74 | incidents.forEach((incident) => { 75 | if (incident.title?.toLowerCase().includes("urgent")) { 76 | incident.urgency = { code: "H", descr: "high" }; 77 | } 78 | }); 79 | } 80 | } 81 | 82 | /** Custom Validation */ 83 | async onUpdate (req) { 84 | const { status_code } = await SELECT.one(req.subject, i => i.status_code).where({ID: req.data.ID}) 85 | if (status_code === 'C') 86 | return req.reject(`Can't modify a closed incident`) 87 | } 88 | } 89 | module.exports = IncidentsService 90 | ``` 91 | 92 | You can read more about [Providing Services](https://cap.cloud.sap/docs/guides/providing-services/) 93 | 94 | *** 95 | 96 | Proceed with the next step: [Adding data](05_node_adding_data.md) -------------------------------------------------------------------------------- /exercises/05_java_adding_data.md: -------------------------------------------------------------------------------- 1 | # Adding Data to your database 2 | 3 | ## Using In-Memory Database 4 | `cds watch` automatically bootstraps a database by default - unless told otherwise. It drastically speeds up turn-around times in local development and furthermore allows self-contained testing. 5 |
6 | 7 | Since we already have an H2 in-memory database that was automatically created, let's now fill it with some test data. 8 | 9 | ### Adding Initial Data in `.csv` Files 10 | 11 | First, make sure that you're in the root directory of the `incidents` application. If you're in the `srv` folder go one up with this command: 12 | 13 | ```sh 14 | cd .. 15 | ``` 16 | 17 | You can fill your database with initial data by adding a few plain CSV files. For each entity that you want to populate with mock-data, you can add the mockdata files using the naming convention `{enityNamespace}-{entityName}.csv` files in the `db/data` folder or use the following command (either in a new terminal or you stop the running `mvn cds watch and restart it later): 18 | 19 | ```sh 20 | cds add data 21 | ``` 22 | 23 | It will generate `.csv` templates which can be filled with the following content. Please make sure that you replace the full content of the file including the header columns. 24 | 25 | `sap.capire.incidents-Conversations.csv` 26 | ```csv 27 | ID, Incidents_ID, timestamp,author,message 28 | 2b23bb4b-4ac7-4a24-ac02-aa10cabd842c,3b23bb4b-4ac7-4a24-ac02-aa10cabd842c, 1995-12-17T03:24:00Z,Cloudy Mac Cloudscale,my cloud does not scale! 29 | 2b23bb4b-4ac7-4a24-ac02-aa10cabd843c,3a4ede72-244a-4f5f-8efa-b17e032d01ee,1995-12-18T04:24:00Z,Gladys Boothby,What exactly is wrong? 30 | 9583f982-d7df-4aad-ab26-301d4a157cd7,3583f982-d7df-4aad-ab26-301d4a157cd7,2022-09-04T12:00:00Z,Sunny Sunshine,"Solar panel is broken, please check" 31 | 9583f982-d7df-4aad-ab26-301d4a158cd7,3ccf474c-3881-44b7-99fb-59a2a4668418,2022-09-04T13:00:00Z,Bradley Flowers,What exactly is wrong? 32 | ``` 33 | 34 | `sap.capire.incidents-Customers.csv` 35 | ```csv 36 | ID,firstName,lastName,email,phone,streetAddress,city,postcode 37 | 8fc8231b-f6d7-43d1-a7e1-725c8e988d18,Cloudy,Mac Cloudscale,cloudy.mac.cloudscale@demo.com,+44-555-123,4 Cloud Road, Cloud City, 1234" 38 | feb04eac-f84f-4232-bd4f-80a178f24a17,Sherlock,Holmes,sherlock.holmes@demo.com,,221B Baker Street,London,NW1 6XE 39 | 2b87f6ca-28a2-41d6-8c69-ccf16aa6389d,Sunny,Sunshine,sunny.sunshine@demo.com,+01-555-789,11111 W Sunset Blv,Los Angeles,90049 40 | ``` 41 | 42 | `sap.capire.incidents-Incidents.csv` 43 | ```csv 44 | ID,customer_ID,title,urgency_code,status_code 45 | 3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,8fc8231b-f6d7-43d1-a7e1-725c8e988d18,my cloud does not scale,H,C 46 | 3a4ede72-244a-4f5f-8efa-b17e032d01ee,feb04eac-f84f-4232-bd4f-80a178f24a17,Ran out of tea,H,N 47 | 3ccf474c-3881-44b7-99fb-59a2a4668418,feb04eac-f84f-4232-bd4f-80a178f24a17,Violin broken,M,N 48 | 3583f982-d7df-4aad-ab26-301d4a157cd7,2b87f6ca-28a2-41d6-8c69-ccf16aa6389d,Solar panel broken,H,I 49 | ``` 50 | 51 | `sap.capire.incidents-Status.csv` 52 | ```csv 53 | code;descr 54 | N;new 55 | A;assigned 56 | I;in_process 57 | H;on_hold 58 | R;resolved 59 | C;closed 60 | ``` 61 | 62 | `sap.capire.incidents-Urgency.csv` 63 | ```csv 64 | code;descr 65 | H;high 66 | M;medium 67 | L;low 68 | ``` 69 | 70 | Once added, the running `mvn cds:watch` will automatically refresh the data. 71 | You can open the application by using `Command Palette` (F1 or Command+Shift+P) -> `Ports: Preview` and selecting the port 8080. In your browser, you will now be able to see the data in the corresponding endpoints. 72 | 73 | In contrast to other tutorials that you run on your local machine you can't use localhost because you don't develop on your local host. ;) 74 | 75 | *** 76 | 77 | Proceed with the next step: [Adding Fiori Elements](06_java_adding_fiori_elements.md) -------------------------------------------------------------------------------- /exercises/05_node_adding_data.md: -------------------------------------------------------------------------------- 1 | # Adding Data to your database 2 | 3 | ## Using a In-Memory Database 4 | `cds watch` automatically bootstraps a database by default - unless told otherwise. It drastically speeds up turn-around times in local development and furthermore allows self-contained testing. 5 |
6 | 7 | Since we already have an SQLite in-memory database that was automatically created, let's now fill it with some test data. 8 | 9 | ### Adding Initial Data in `.csv` Files 10 | 11 | You can fill your database with initial data by adding a few plain CSV files. For each entity that you want to populate with mock-data, you can add the mockdata files using the naming convention `{enityNamespace}-{entityName}.csv` files in the `db/data` folder or use the following command (either in a new terminal or you stop the running `cds watch` for now): 12 | 13 | ```sh 14 | cds add data 15 | ``` 16 | 17 | It will generate `.csv` templates which can be filled with the following content. Please make sure that you replace the full content of the file including the header columns. 18 | 19 | `sap.capire.incidents-Conversations.csv` 20 | ```csv 21 | ID, Incidents_ID, timestamp,author,message 22 | 2b23bb4b-4ac7-4a24-ac02-aa10cabd842c,3b23bb4b-4ac7-4a24-ac02-aa10cabd842c, 1995-12-17T03:24:00Z,Cloudy Mac Cloudscale,my cloud does not scale! 23 | 2b23bb4b-4ac7-4a24-ac02-aa10cabd843c,3a4ede72-244a-4f5f-8efa-b17e032d01ee,1995-12-18T04:24:00Z,Gladys Boothby,What exactly is wrong? 24 | 9583f982-d7df-4aad-ab26-301d4a157cd7,3583f982-d7df-4aad-ab26-301d4a157cd7,2022-09-04T12:00:00Z,Sunny Sunshine,"Solar panel is broken, please check" 25 | 9583f982-d7df-4aad-ab26-301d4a158cd7,3ccf474c-3881-44b7-99fb-59a2a4668418,2022-09-04T13:00:00Z,Bradley Flowers,What exactly is wrong? 26 | ``` 27 | 28 | `sap.capire.incidents-Customers.csv` 29 | ```csv 30 | ID,firstName,lastName,email,phone,streetAddress,city,postcode 31 | 8fc8231b-f6d7-43d1-a7e1-725c8e988d18,Cloudy,Mac Cloudscale,cloudy.mac.cloudscale@demo.com,+44-555-123,4 Cloud Road, Cloud City, 1234" 32 | feb04eac-f84f-4232-bd4f-80a178f24a17,Sherlock,Holmes,sherlock.holmes@demo.com,,221B Baker Street,London,NW1 6XE 33 | 2b87f6ca-28a2-41d6-8c69-ccf16aa6389d,Sunny,Sunshine,sunny.sunshine@demo.com,+01-555-789,11111 W Sunset Blv,Los Angeles,90049 34 | ``` 35 | 36 | `sap.capire.incidents-Incidents.csv` 37 | ```csv 38 | ID,customer_ID,title,urgency_code,status_code 39 | 3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,8fc8231b-f6d7-43d1-a7e1-725c8e988d18,my cloud does not scale!,H,C 40 | 3a4ede72-244a-4f5f-8efa-b17e032d01ee,feb04eac-f84f-4232-bd4f-80a178f24a17,Ran out of tea,H,N 41 | 3ccf474c-3881-44b7-99fb-59a2a4668418,feb04eac-f84f-4232-bd4f-80a178f24a17,Violin broken,M,N 42 | 3583f982-d7df-4aad-ab26-301d4a157cd7,2b87f6ca-28a2-41d6-8c69-ccf16aa6389d,Solar panel broken,H,I 43 | ``` 44 | 45 | `sap.capire.incidents-Status.csv` 46 | ```csv 47 | code;descr 48 | N;new 49 | A;assigned 50 | I;in_process 51 | H;on_hold 52 | R;resolved 53 | C;closed 54 | ``` 55 | 56 | `sap.capire.incidents-Urgency.csv` 57 | ```csv 58 | code;descr 59 | H;high 60 | M;medium 61 | L;low 62 | ``` 63 | 64 | Once added, the running `cds watch` will automatically refresh the data. 65 | 66 | You can open the application by using `Command Palette` (F1 or Command+Shift+P) -> `Ports: Preview` and selecting the port 4004. Alternatively, you can click the http://localhost:4004 link in the `cds watch` log output (which is automatically redirected to the correct cloud URL). In your browser, you will now be able to see the data in the corresponding endpoints. 67 | 68 | In contrast to other tutorials that you run on your local machine you can't use localhost because you don't develop on your local host. ;) 69 | 70 | *** 71 | 72 | Proceed with the next step: [Adding Fiori Elements](06_node_adding_fiori_elements.md) 73 | -------------------------------------------------------------------------------- /exercises/06_java_adding_fiori_elements.md: -------------------------------------------------------------------------------- 1 | # Adding Fiori elements UIs 2 | 3 | SAP Fiori elements provides designs for UI patterns and predefined floorplans for common application use cases. One can use SAP Fiori elements to create SAP Fiori applications based on OData services and annotations that don't need JavaScript UI coding. The resulting app uses predefined views and controllers based on SAPUI5 that are provided centrally. This means no application-specific view instances are required. SAP Fiori elements interprets metadata and annotations of the underlying OData service and uses the corresponding views for the SAP Fiori app at startup. 4 | 5 | ## Generate the UI with an SAP Fiori elements template 6 | 7 | 1. In BAS, invoke the Command Palette (`Settings -> Command Palette`) and choose `Fiori: Open Application Generator`. 8 | 9 | 2. Choose application type `SAP Fiori` and template `List Report Page`. 10 |
11 | 12 | ![Template Selection](./assets/template_selection_java.png) 13 |
14 | 15 | 3. Choose `Next` 16 | 17 | 4. In the next dialog, choose `Use a Local CAP Project` and choose your current `incidents` project. 18 | 19 | 5. Select the `IncidentsService(Java)` as the OData service and choose `Next` 20 |
21 | 22 | ![Data Source Selection](./assets/data_source_java.png) 23 |
24 | 25 | 6. Select `Incidents` as the main entity, `conversations` as the Navigation entity. Choose `Next` 26 |
27 | 28 | ![Entity Selection](./assets/entity_selection.png) 29 | 30 | 7. Enter `incidents` as the module name and `Incident-Management` as the application title. 31 | 32 | 8. Enter `ns` as the namespace. 33 |
34 | 35 | ![Project Attributes](./assets/project_attributes_java.png) 36 |
37 | 38 | 9. In the upcoming steps, leave the default value for all other settings. 39 | 40 | 10. Choose `Finish` to generate the application. The application is now generated and in a few seconds you can see it in the `app` folder of your project. It contains a `incidents` and a `webapp` folder with a `Component.js` file that is characteristic for an SAPUI5 app. The process is finished when the "Application Information" screen for the newly generated UI appears. 41 | 42 | 11. In order to have a working UI you need to add the following content to your UI annotations in `app/incidents/annotations.cds`: 43 | 44 | ```cds 45 | annotate service.Incidents with @( 46 | UI.LineItem : [ 47 | { 48 | $Type : 'UI.DataField', 49 | Value : title, 50 | }, 51 | { 52 | $Type : 'UI.DataField', 53 | Label : 'urgency_code', 54 | Value : urgency_code, 55 | }, 56 | { 57 | $Type : 'UI.DataField', 58 | Label : 'status_code', 59 | Value : status_code, 60 | }, 61 | ] 62 | ); 63 | annotate service.Incidents with @( 64 | UI.FieldGroup #GeneratedGroup1 : { 65 | $Type : 'UI.FieldGroupType', 66 | Data : [ 67 | { 68 | $Type : 'UI.DataField', 69 | Value : title, 70 | }, 71 | { 72 | $Type : 'UI.DataField', 73 | Label : 'urgency_code', 74 | Value : urgency_code, 75 | }, 76 | { 77 | $Type : 'UI.DataField', 78 | Label : 'status_code', 79 | Value : status_code, 80 | }, 81 | ], 82 | }, 83 | UI.Facets : [ 84 | { 85 | $Type : 'UI.ReferenceFacet', 86 | ID : 'GeneratedFacet1', 87 | Label : 'General Information', 88 | Target : '@UI.FieldGroup#GeneratedGroup1', 89 | }, 90 | ] 91 | ); 92 | ``` 93 | 94 |
95 | 96 | 12. Browse the generated appliction. Restart the `mvn cds:watch` command (in the `srv` folder) in case it's still running (if not just start it) and open the index page in your browser. To do so, open the Command Palette (`Setting` -> `Command Palette` and choose `Ports: Preview`. There, select the entry with port 8080 (the CAP Java default port). Now append `/incidents/webapp/index.html` to the URL in your browser`s address bar. 97 | 98 | 13. In the application you can click the "go" button on the right hand side and load all incidents from the database. By clicking an incident from the list you can open the details view. Use the browser's `back` button to navigate back to the list. 99 | 100 | 101 | *** 102 | 103 | Proceed with the next step: [Adding authorization](07_java_adding_authorization.md) 104 | -------------------------------------------------------------------------------- /exercises/06_node_adding_fiori_elements.md: -------------------------------------------------------------------------------- 1 | # Adding Fiori elements UIs 2 | 3 | SAP Fiori elements provides designs for UI patterns and predefined floorplans for common application use cases. One can use SAP Fiori elements to create SAP Fiori applications based on OData services and annotations that don't need JavaScript UI coding. The resulting app uses predefined views and controllers based on SAPUI5 that are provided centrally. This means no application-specific view instances are required. SAP Fiori elements interprets metadata and annotations of the underlying OData service and uses the corresponding views for the SAP Fiori app at startup. 4 | 5 | ## Generate the UI with an SAP Fiori elements template 6 | 7 | 1. In BAS, invoke the Command Palette (`Settings -> Command Palette`) and choose `Fiori: Open Application Generator`. 8 | 9 | 2. Choose application type `SAP Fiori` and template `List Report Page`. 10 |
11 | 12 | ![Template Selection](./assets/template_selection.png) 13 |
14 | 15 | 3. Choose `Next` 16 | 17 | 4. In the next dialog, choose `Use a Local CAP Project` and choose your current `incidents-mgmt` project. 18 | 19 | 5. Select the `IncidentsService(Node.js)` as the OData service and choose `Next` 20 |
21 | 22 | ![Data Source Selection](./assets/data_source.png) 23 |
24 | 25 | 6. Select `Incidents` as the main entity, `conversations` as the Navigation entity. Choose the option `Yes` to add table columns automatically. Choose `Next` 26 |
27 | 28 | ![Entity Selection](./assets/entity_selection.png) 29 | 30 | 7. Enter `incidents` as the module name and `Incident-Management` as the application title. 31 | 32 | 8. Enter `ns` as the namespace. 33 |
34 | 35 | ![Project Attributes](./assets/project_attributes.png) 36 |
37 | 38 | 9. In the upcoming steps, leave the default value for all other settings. 39 | 40 | 10. Choose `Finish` to generate the application. 41 |
42 | 43 | The application is now generated and in a few seconds you can see it in the `app` folder of your project. It contains a `incidents` and a `webapp` folder with a `Component.js` file that is characteristic for an SAPUI5 app. 44 | 45 | 11. Browse the generated application 46 | 47 | Once the application generation wizard is completed the `app` folder contains a new folder with the generated application. Start the `cds watch` command in case it's not running anymore and open the index page in your browser. To do so, you have 2 options: 48 | 49 | * From the log output of the running applicatoin you can click the http://localhost:4004 link. Don't enter it manually to the browser but only click the link from the log. It will redirect you to the right "cloud localhost". :) 50 | * Alternatively, open the Command Palette (`Setting` -> Command Palette`` and choose `Ports: Preview`. There, select the entry with port 4004 (the CAP node.js default port). Now, the index page of your CAP application is displayed and has an entry for the just generated UI. Navigate the link and browse the new application. 51 | 52 | In the application you can click the "go" button on the right hand side and load all incidents from the database. By clicking an incident from the list you can open the details view. Use the browser's `back` button to navigate back to the list. 53 | 54 | *** 55 | 56 | Proceed with the next step: [Adding authorization](07_node_adding_authorization.md) -------------------------------------------------------------------------------- /exercises/07_java_adding_authorization.md: -------------------------------------------------------------------------------- 1 | # Authorization and Authentication 2 | 3 | Authorization means restricting access to data by adding respective declarations to CDS models, which are then enforced in service implementations. Individual privileges are given by adding such declarations. While, authorization verifies the user's identity and the presented claims such as granted roles and tenant membership. 4 | 5 | ## Prepare User Authentication and Authorization (XSUAA) Setup 6 | 7 | ### Roles and scopes 8 | A scope represents a single authorization to perform an action. For example, there could be a scope “Read” and a scope “Write”. The scope allows a user to read or write a certain business object. Scopes can’t be assigned to users directly. They’re packaged into roles. For example, there could a role “Editor” consisting of the “Read” and “Write” scopes, while the role “Viewer” consists only of the “Read” scope. 9 | 10 |

11 | For this example, we can add access restriction to our `CustomersService`. 12 | 13 | Edit the `srv/incidents-service.cds` file as follows: 14 | 15 | ```sh 16 | service IncidentsService @(requires: 'admin') { 17 | ... 18 | } 19 | ``` 20 | 21 | This will make the incidents service accesible to only the `admin` roles. 22 | Once the server is reloaded, a pop-up will come on IncidentsService, we can check our implementation here. 23 | 24 | `@sap/cds` has some users as default configuration. You can use `alice` as username to check for the `admin` right and `bob` as username to check for when the `admin` right are not there. When you use `alice`, you will be able to access the application whereas when you use `bob`, it will throw an error. 25 | 26 | We can define the roles in our `srv/src/main/resources/application.yaml` by adding the following snippet in there *under the cds node*: 27 | 28 | ```yaml 29 | security.mock.users: 30 | - name: admin1 31 | password: abcd 32 | roles: 33 | - admin 34 | ``` 35 | 36 | The complete `srv/src/main/resources/application.yaml` file needs to look like this: 37 | 38 | ```yaml 39 | --- 40 | spring: 41 | config.activate.on-profile: default 42 | cds: 43 | datasource: 44 | auto-config.enabled: false 45 | security.mock.users: 46 | - name: admin1 47 | password: abcd 48 | roles: 49 | - admin 50 | ``` 51 | 52 | Addtionally, you need to add the Spring Boot Security starter module to the `` section in the `pom.xml` file in the `srv` folder of your application: 53 | 54 | ```xml 55 | 56 | org.springframework.boot 57 | spring-boot-starter-security 58 | 59 | ``` 60 | 61 | You can check the access to the application by using the new credentials (username: admin1 and password: abcd) now. 62 |
63 | 64 | To learn more about Authorization and Authentication methods, you can refer [here](https://cap.cloud.sap/docs/guides/authorization#prerequisite-authentication) 65 | 66 | *** 67 | 68 | Congratulations! You finished the CAP Getting Started tutorial. 69 | -------------------------------------------------------------------------------- /exercises/07_node_adding_authorization.md: -------------------------------------------------------------------------------- 1 | # Authorization and Authentication 2 | 3 | Authorization means restricting access to data by adding respective declarations to CDS models, which are then enforced in service implementations. Individual privileges are given by adding such declarations. While, authorization verifies the user's identity and the presented claims such as granted roles and tenant membership. 4 | 5 | ## Prepare User Authentication and Authorization (XSUAA) Setup 6 | 7 | ### Roles and scopes 8 | A scope represents a single authorization to perform an action. For example, there could be a scope “Read” and a scope “Write”. The scope allows a user to read or write a certain business object. Scopes can’t be assigned to users directly. They’re packaged into roles. For example, there could a role “Editor” consisting of the “Read” and “Write” scopes, while the role “Viewer” consists only of the “Read” scope. 9 | 10 |

11 | For this example, we can add access restriction to our `CustomersService`. 12 | 13 | Edit the `srv/incidents-service.cds` file as follows: 14 | 15 | ```sh 16 | service IncidentsService @(requires: 'admin') { 17 | ... 18 | } 19 | ``` 20 | 21 | This will make the incidents service accesible to only the `admin` roles. 22 | Once the server is reloaded, a pop-up will come on IncidentsService, we can check our implementation here. 23 | 24 | We can define the roles in our `package.json` by adding the following snippet as node *below the top level object*: 25 | 26 | ```sh 27 | "cds":{ 28 | "requires":{ 29 | "auth":{ 30 | "kind": "basic", 31 | "users": { 32 | "admin1": { 33 | "password": "abcd", 34 | "roles": [ 35 | "admin" 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | } 42 | ``` 43 | 44 | You can check the access to the application by using these credentials now. 45 |
46 | 47 | To learn more about Authorization and Authentication methods, you can refer [here](https://cap.cloud.sap/docs/guides/authorization#prerequisite-authentication) 48 | 49 | *** 50 | 51 | Congratulations! You finished the CAP Getting Started tutorial. 52 | -------------------------------------------------------------------------------- /exercises/08_java_optional_add_multitenancy.md: -------------------------------------------------------------------------------- 1 | # Adding multitenancy to the application 2 | 3 | Multitenancy is the ability to serve multiple tenants through single clusters of micro service instances, while ensuring strict isolation with respect to tenants data and access to it. Tenants are clients using SaaS solutions. 4 | 5 | In contrast to single-tenant mode, applications aren't serving end-user request immediately after deployment, but wait for tenants to subscribe. 6 |
7 | 8 | CAP has built-in support for multitenancy with the `@sap/cds-mtx` package. 9 |
10 | 11 | ## Enable Multitenancy 12 | 13 | Execute the following command in the p[roject root" 14 |
15 | 16 | ```sh 17 | cds add multitenancy 18 | ``` 19 | This command does the following two steps: 20 | 21 | 1. Add `@sap/cds-mtxs` package dependeny 22 | 23 | ```sh 24 | npm add @sap/cds-mtxs 25 | ``` 26 | 27 | 2. Switch on cds.requires.multitenancy 28 | Adds the following configuration to the `package.json`: 29 | 30 | ```cds 31 | "cds":{ 32 | "requires":{ 33 | "multitenancy": true 34 | } 35 | } 36 | ``` 37 | 38 | Now, run `npm install` to update the node modules: 39 | 40 | ```sh 41 | npm install 42 | ``` 43 | 44 | ## Testing Locally 45 | 46 | To test multitenancy, just run the CAP server, and then log on with different users, assigned to different tenants, to see the effects 47 | 48 | Start the server: 49 | 50 | ```sh 51 | cds watch 52 | ``` 53 | 54 | This produces an output like: 55 |
56 | 57 | ![Multitenancy](./assets/mtx.png) 58 |
59 | 60 | In contrast to single-tenant mode, we recognize differences in the log output with regards to the database initialization and the services that are bootstrapped. 61 | -------------------------------------------------------------------------------- /exercises/08_node_optional_add_multitenancy.md: -------------------------------------------------------------------------------- 1 | # Adding multitenancy to the application 2 | 3 | Multitenancy is the ability to serve multiple tenants through single clusters of micro service instances, while ensuring strict isolation with respect to tenants data and access to it. Tenants are clients using SaaS solutions. 4 | 5 | In contrast to single-tenant mode, applications aren't serving end-user request immediately after deployment, but wait for tenants to subscribe. 6 |
7 | 8 | CAP has built-in support for multitenancy with the `@sap/cds-mtx` package. 9 |
10 | 11 | ## Enable Multitenancy 12 | 13 | Execute the following command in the p[roject root" 14 |
15 | 16 | ```sh 17 | cds add multitenancy 18 | ``` 19 | This command does the following two steps: 20 | 21 | 1. Add `@sap/cds-mtxs` package dependeny 22 | 23 | ```sh 24 | npm add @sap/cds-mtxs 25 | ``` 26 | 27 | 2. Switch on cds.requires.multitenancy 28 | Adds the following configuration to the `package.json`: 29 | 30 | ```cds 31 | "cds":{ 32 | "requires":{ 33 | "multitenancy": true 34 | } 35 | } 36 | ``` 37 | 38 | Now, run `npm install` to update the node modules: 39 | 40 | ```sh 41 | npm install 42 | ``` 43 | 44 | ## Testing Locally 45 | 46 | To test multitenancy, just run the CAP server, and then log on with different users, assigned to different tenants, to see the effects 47 | 48 | Start the server: 49 | 50 | ```sh 51 | cds watch 52 | ``` 53 | 54 | This produces an output like: 55 |
56 | 57 | ![Multitenancy](./assets/mtx.png) 58 |
59 | 60 | In contrast to single-tenant mode, we recognize differences in the log output with regards to the database initialization and the services that are bootstrapped. 61 | -------------------------------------------------------------------------------- /exercises/assets/Terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/Terminal.png -------------------------------------------------------------------------------- /exercises/assets/create_dev_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/create_dev_space.png -------------------------------------------------------------------------------- /exercises/assets/create_space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/create_space.png -------------------------------------------------------------------------------- /exercises/assets/data_source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/data_source.png -------------------------------------------------------------------------------- /exercises/assets/data_source_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/data_source_java.png -------------------------------------------------------------------------------- /exercises/assets/domain.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Incidents
Incidents
conversation
conversation
Customers
Customers
Messages
Messages
Service
Workers
Service...
repair
repair
Appointments
Appointments
Text is not SVG - cannot display
-------------------------------------------------------------------------------- /exercises/assets/entity_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/entity_selection.png -------------------------------------------------------------------------------- /exercises/assets/entity_selection_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/entity_selection_java.png -------------------------------------------------------------------------------- /exercises/assets/full_stack_application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/full_stack_application.png -------------------------------------------------------------------------------- /exercises/assets/incidents_mgmt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/incidents_mgmt.png -------------------------------------------------------------------------------- /exercises/assets/incidents_mgmt_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/incidents_mgmt_java.png -------------------------------------------------------------------------------- /exercises/assets/java_auto_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/java_auto_build.png -------------------------------------------------------------------------------- /exercises/assets/java_auto_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/java_auto_save.png -------------------------------------------------------------------------------- /exercises/assets/mtx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/mtx.png -------------------------------------------------------------------------------- /exercises/assets/open_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/open_folder.png -------------------------------------------------------------------------------- /exercises/assets/project_attributes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/project_attributes.png -------------------------------------------------------------------------------- /exercises/assets/project_attributes_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/project_attributes_java.png -------------------------------------------------------------------------------- /exercises/assets/services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/services.png -------------------------------------------------------------------------------- /exercises/assets/services_java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/services_java.png -------------------------------------------------------------------------------- /exercises/assets/spaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/spaces.png -------------------------------------------------------------------------------- /exercises/assets/template_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cap-js/cap-getting-started-tutorial/9799a6d2fa12647dff296c0b035498cfb4b4f96f/exercises/assets/template_selection.png --------------------------------------------------------------------------------