Skip to content
This repository has been archived by the owner on Oct 9, 2021. It is now read-only.

Commit

Permalink
First content
Browse files Browse the repository at this point in the history
  • Loading branch information
chgeo committed Aug 30, 2019
1 parent 1d23d87 commit da901c1
Show file tree
Hide file tree
Showing 19 changed files with 301 additions and 2 deletions.
33 changes: 31 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,31 @@
# cloud-cap-walkthroughs
This project contains exercises and tutorials for SAP Cloud Application Programming Model.
# Samples for the SAP Cloud Application Programming Model

This repository contains tutorials for the sample apps of the SAP Cloud Application Programming Model.

## Requirements

For local execution:
- Node.js, version 8 or 10

For deploying to SAP HANA on SAP Cloud Platform (Cloud Foundry):
- Service 'SAP HANA Schemas & HDI Containers'

You may want use a **free trial account** for SAP Cloud Platform. Follow this [tutorial to create a trial account](https://developers.sap.com/tutorials/hcp-create-trial-account.html).


## Tutorials


### [Getting started with the SAP Cloud Application Programming Model ](exercises-java/readme.md)

<!-- ### [Rapid Service Development with SAP Cloud Application Programming Model](exercises-node/) -->



## How to obtain support

Support for this content will be provided only within the context of SAP TechEd 2019. Otherwise, this content is provided "as-is" with no other support.

## License

<a rel="license" href="http:https://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http:https://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License</a>.
40 changes: 40 additions & 0 deletions exercises-java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Scenario

Welcome to the SAP Cloud Application Programming Model hands-on session! Wow... that's a mouthful. From now on, let's just call it CAP hands-on. During this session, you'll learn how to use CAP to build an online store, in this case, a store for books or bookstore, as we like to call it.
So, we've established that "books" will be your product of choice for this exercise. The interesting thing about CAP, is that you can easily build services, but also reuse an existing service to make your development life easier. In this case, we'll show you how to reuse a products service.
Before you get started, it's important to understand that CAP is both open & opinionated. That might sound like an oximoron, but it's really quite simple. It's opinionated because you can choose to follow our guidance and develop along our golden path of best practices. However, it's open because you can also choose your own path, typical freestyle-style.
Ready? Let's get started...

## Excercises

### [Exercise 1: Getting started: Development environment and Hello World](exercise1/README.md)

First things first, you need to set up your development environment and check that everything is running smoothly.

For this exercise, we'll use SAP Web IDE as the development tool of choice. This version of SAP Web IDE is not what you're used to. It's a completely new version that provides a web-based Visual Studio Code-like experience. So it's like VS Code, but for your browser.
What's great about using SAP Web IDE? You get an editor, useful extensions and all the tools required to develop CAP applications as well as full access to the terminal.

To make sure everything is set up correctly, this exercise also includes how to build & run a simple Hello World application.
CAP supports both Java and Node.js development. But for this exercise, we'll be using Java. The CAP Java stack is able to tightly integrate with [Spring Boot](https://spring.io/projects/spring-boot), which provides a lot of features out of the box. This means, Spring Boot will be your runtime container.

<!-- ### [Exercise 2: Creating a reusable Products Service](exercise2/README.md)
The last exercise was about quickly setting up a working CAP application. This exercise is about learning how to extend the application and to build a complete products service. You'll take advantage of all the out-of-the-box features provided by the CAP Java Stack. As a result, you'll remove your custom handlers and use SQLite as a database for local development. Later, in Exercise 5, you will swap out SQLite with the SAP HANA service, when preparing your application for the cloud.
### [Exercise 3: Building the Bookstore](exercise3/README.md)
Now that your products service is ready to be reused, you will build your bookstore application. In this exercise you will create the model and the services of the bookstore application.
After that you will initialize the SQLite database of your bookstore application with localized example data coming from CSV files.
You will then run your application - still without any custom coding required - and see the localization features of CAP in action.
### [Exercise 4: Extending the Bookstore with custom code](exercise4/README.md)
In the last exercise you built the data model and exposed the services of your bookstore application. In this exercise you will extend the bookstore with custom code to calculate the `total` and `netAmount` elements of the `Orders` and `OrderItems` entity. In addition when creating an order the available stock of a book will be checked and decreased.
### [Exercise 5: Using SAP HANA as database](exercise5/README.md)
In this exercises you will make the application ready to be deployed to the cloud. In order to make our application cloud-ready, we'll switch to SAP HANA as our database.
### [Exercise 6: Deploying to the cloud](exercise6/README.md)
In the last exercise you made your application ready to be running with SAP HANA. In this exercise you deploy the application to SAP Cloud Platform Cloud Foundry Environment and have it running fully in the cloud. -->
230 changes: 230 additions & 0 deletions exercises-java/exercise1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# Exercise 1 - Get started: Development environment and Hello World

First things first, you need to set up your development environment and check that everything is running smoothly.

For this exercise, we'll use SAP Web IDE as the development tool of choice. This version of SAP Web IDE is not what you're used to. It's a completely new version that provides a web-based Visual Studio Code-like experience. So it's like VS Code, but for your browser. What's great about using SAP Web IDE? You get an editor, useful extensions and all the tools required to develop CAP applications and full access to the terminal.

To make sure everything is set up correctly, this exercise also includes how to build & run a simple Hello World application. CAP supports both Java and Node.js development. But for this exercise, we'll be using Java. The CAP Java stack is able to tightly integrate with Spring Boot, which provides a lot of features out of the box. This means, Spring Boot will be your runtime container.

## Open SAP Web IDE and create your Dev Space

Before you can start using SAP Web IDE, you need to create your developer space, where your project will run. Depending on the application you want to develop, you can create different dev spaces. For this hands-on session, you'll create a dev space personalized for building services and applications with CAP.

1. Go to the URL for SAP Web IDE given by the instructor.

2. Choose **Create Dev Space**.

![create_dev_space](./images/create_dev_space.png)

3. Choose a name for your dev space. For example **TechEd19_XXX**. **XXX** is the number given to you by your instructor.

4. Choose **SAP Cloud Business Application** as the application type.

By selecting **SAP Cloud Business Application**, your space comes with several extensions out of the box that you'll need to develop CAP applications. For example, CDS tools are built in. This saves unnecessary setup time.

5. Choose **Create Dev Space**.

![configure_dev_space](./images/configure_dev_space.png)

The creation of the dev space takes a few seconds. When it's ready, you can open your dev space by clicking on the name.

![open_dev_space](./images/open_dev_space.png)

## Initialize the application

1. In SAP Web IDE, choose **Open Workspace**:

![choose_open_ws](./images/choose_open_ws.png)

Make sure **Projects** is selected form the drop-down menu and choose **Open**.

![open_ws_dialog](./images/open_ws_dialog.png)

2. From the main menu, choose **Terminal, New Terminal**.

![open_terminal](./images/open_terminal.png)

3. From the terminal run:

```bash
mvn -B archetype:generate -DarchetypeArtifactId=cds-services-archetype -DarchetypeGroupId=com.sap.cds -DarchetypeVersion=1.0.0-1935 \
-DgroupId=com.sap.teched.cap -DartifactId=products-service -Dpackage=com.sap.teched.cap.productsservice
```

This will initialize the application and create your project as follows:

- The project is named `products-service`. You will also reuse it in [Exercise 2](../exercise2/README.md).
- The `db` folder stores database related artifacts.
- The `srv` folder stores your Java application.

4. The project you just created contains some sample data. Since part of this exercise is showing you how to add your own data, we need to delete the sample data.

a. Go to the **products_service** folder and expand the **db** folder.

b. Right-click on the `data-model.cds` file and choose **Delete** from the context menu.

![delete_sample](./images/delete_sample.png)

c. Expand the **srv** folder and delete the `cat-service.cds`file.

## Define a service

CAP applications use CDS (Core Data Services) to:
- describe data structures by using Entity definitions
- describe how data structures are consumed by using Service definitions

In this step, you'll define a simple service, which also defines it's own entity. In more complex applications, services usually expose projections on entities defined in the data model. You will see this later in [Exercise 2](../exercise2/README.md).

1. Right-click on the `srv` folder, choose **New File** and name it `admin-service.cds`

![create_new_file](./images/create_new_file.png)

2. Choose **OK** to create the file.

![new_file_srv](./images/new_file_srv.png)

3. Add the following service defintion to the file:

```swift
service AdminService {
entity Products {
key ID : Integer;
title : String(111);
descr : String(1111);
}
}
```

4. Go to the root of your **products-service** project by running `cd ~/projects/products-service` within the terminal. After that run `mvn clean install` to compile the model definition. Note that running this for the first time in a fresh dev space might take a while, depending on the network.

![build_success](./images/build_success.png)

After running this command, some files are generated and added to the `srv/src/main/resources/edmx` folder. This is the default path, where CAP Java runtime looks for the model definitions.

![edmx_files](./images/edmx_files.png)

## Run your application

While initializing the application an `Application.java` file was created, which contains a `main` method. The `Application.java` is the startup class for the Spring Boot container.

Take a look at the `Application.java` in the `com.sap.teched.cap.productsservice` package (file path: `srv/src/main/java/com/sap/teched/cap/productsservice`).

![app_file_path](./images/app_file_path.png)

As you can see, the file does not contain CAP specific startup instructions. It is the typical boilerplate code found in every Spring Boot application.

The initialization of the CAP Java runtime is done by Spring automatically, based on the dependencies defined in the `pom.xml`.

1. To start the application, go to the root of your project (`cd ~/projects/products-service`) in the terminal and run `mvn spring-boot:run`

2. A notifaction tab saying "A service is listenning to port 8080" will appear.

a. Choose `Expose and Open` and provide `app-port` as the unique description.

![expose_open_port](./images/expose_open_port.png)

b. Press `Enter`and the application opens in a new tab.

**Hint**: In case you missed the notification tab "A service is listenning to port 8080", you can reopen it:

1. Go to **View** --> **Find Command** --> **Ports: Expose**.

2. Select or enter `8080` and provide `app-port` as the unique description.

You can also use the Command Palette ports command to preview, unexpose and rename ports.

4. Add `/odata/v4/AdminService/$metadata` to your app URL to inspect the OData metadata, which is automatically served by the CAP Java runtime.

"<APP_URL>" is the URL created when you run your application. When you first open it in a new tab, you'll see a welcome page. After adding `/odata/v4/AdminService/$metadata`, you'll see the OData metadata.

![odata_metadata_url](./images/odata_metadata_url.png)

In the next step, you'll learn how to add custom logic. Specifically, so that your application can read and create Products.

## Add a custom event handler

Later on in the session, you'll learn that CAP Java runtime can handle all CRUD events (create, read, update and delete) triggered by OData requests out of the box.

However for now, we'll show you how to do this manually, so that you can see how to easily write a custom event handler to extend the event handling process.

1. Create the Java package, by creating a new folder `handlers` under `srv/src/main/java/com/sap/teched/cap/productsservice`.

2. Create the Java class file `AdminService.java` in the created `handlers` folder, with the following content:

```Java
package com.sap.teched.cap.productsservice.handlers;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Component;

import com.sap.cds.services.cds.CdsCreateEventContext;
import com.sap.cds.services.cds.CdsReadEventContext;
import com.sap.cds.services.cds.CdsService;
import com.sap.cds.services.handler.EventHandler;
import com.sap.cds.services.handler.annotations.On;
import com.sap.cds.services.handler.annotations.ServiceName;

@Component
@ServiceName("AdminService")
public class AdminService implements EventHandler {

private Map<Object, Map<String, Object>> products = new HashMap<>();

@On(event = CdsService.EVENT_CREATE, entity = "AdminService.Products")
public void onCreate(CdsCreateEventContext context) {
context.getCqn().entries().forEach(e -> products.put(e.get("ID"), e));
context.setResult(context.getCqn().entries());
}

@On(event = CdsService.EVENT_READ, entity = "AdminService.Products")
public void onRead(CdsReadEventContext context) {
context.setResult(products.values());
}

}
```

This class now handles the `READ` and `CREATE` events that target the `Products` entity of the `AdminService`.
- The `READ` operation just returns all entities kept in memory.
- The `CREATE` event extracts the payload from the CQN representation and stores it in memory.

CQN (CDS Query Notation) is the common language in CAP to run queries against services. It can be used to talk to the services defined by your model, but also remote services, such as the database.

The event handler uses the following APIs, which are available for Service Providers in CAP Java:

* Event handler classes have to implement the marker interface `EventHandler` and register themselves as Spring Beans (`@Component`). The marker interface is important, because it enables the CAP Java runtime to identify these classes among all Spring Beans.
* Event handler methods are registered with `@On`, `@Before` or `@After` annotations. Every event, such as an entity creation, runs through these three phases. Each phase has a slightly different semantic. You will learn more about these semantics in [Exercise 4](../exercise4/README.md).
* The annotation `@ServiceName` specifies the default service name all event handler methods apply to. Here this is `AdminService`, as this was also the name when defining the service in the CDS model.
* Event handler methods get an event-specific event context parameter, which provides access to the input parameters of the event and the ability to set the result. For example, let's look at the `CdsCreateEventContext context` parameter. The event we are extending is the `CREATE` event. The type of the context variable is specific to this extended `CREATE` event. The `onCreate` method returns `void`, as the result is set by running: `context.setResult(…)`.

3. Stop your application if it is still running in the terminal, by pressing `CTRL + C`.

4. Start your application again by running `mvn spring-boot:run` in the terminal.

Choose **Open in a new tab** when prompted.

5. Try to insert some data. For example, use curl from a new terminal to run the following request.

You can open terminals by choosing **Terminal, New Terminal** from the main menu.

```bash
curl -X POST http:https://localhost:8080/odata/v4/AdminService/Products \
-H "Content-Type: application/json" \
-d '{"ID": 42, "title": "Awesome product", "descr": "It is really really awesome!"}'
```

6. To read the data again, open the following URL in your browser:

`<APP_URL>/odata/v4/AdminService/Products`

You should see something like this:

![custom_logic_01](./images/custom_logic_01.png)

## Great job!

You have successfully developed a basic CAP Java application AND added custom logic to handle specific requests.
[Exercise 2](../exercise2/README.md) will show you how to extend the application and build the products service from scratch.
In addition, you will use an actual database as the persistence and see some of the features the CAP Java stack provides out of the box, without a single line of custom coding.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises-java/exercise1/images/build_success.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises-java/exercise1/images/delete_sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises-java/exercise1/images/edmx_files.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises-java/exercise1/images/new_file_srv.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises-java/exercise1/images/open_terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit da901c1

Please sign in to comment.