SAP Tutorial: Complete CAP Java Part 2

Brian Heise
Nerd For Tech
Published in
9 min readJun 10, 2021

Adding mock data, API settings, serving UIs, and creating mock users

Photo by Joshua Aragon on Unsplash

Contents

Welcome to Complete CAP Java Part 2. In this tutorial series, I’ll show you how to build SAP’s bookshop sample app for CAP Java step by step. This tutorial series assumes no prior knowledge, so anyone can follow along. Be sure to check out Part 1 to see what we’ve been doing up until now.

Step 1: Adding Mock Data

We ended part one by using the REST Client addon for VS Code to test our oData API, which let us add in a little data to our database. As we’re developing, though, we’re going to want a consistent set of mock data to work with, and we don’t want to have manually submit it every time. Luckily, a database seeding feature is built into CAP, so as long as we have a CSV file containing our mock data, we can have it automatically deployed to our dev database each time we start up the app. Let’s make such a file for our books model.

Go to your database folder and create a subfolder called “data”, and inside create a CSV file. The name of the file is important because it’s how CAP locates the file and associates it with the correct data model. The pattern is <namespace>-<model_name>.csv. In Part 1 of this series we made our namespace toadslop.bookshop and named our model Books, so our file should be called toadslop.bookshop-Books.csv.

The header line of your CSV should be the names of the elements defined in our Books model, as shown below. Feel free to add whatever data you like. Or, if you just want to copy something, checkout the Git repo for this project and copy it (make sure you find the commit that matches Part 2 - Step 1; the data model will change in later steps, making the mock data file invalid for this step).

ID;TITLE;DESCR;AUTHOR;GENRE;

After you’ve entered your mock data, run mvn spring-boot:run and try out our get request from the REST client file we made in Part 1 to see if you get your data.

Note that if your app fails to start, it’s likely because there’s a mistake in the name of your csv file. Scan your output for the following error message:

Caused by: com.sap.cds.services.utils.ErrorStatusException: Can't find an entity 'toadslop.bookshop.Boks' matching CSV file '../db/data/toadslop.bookshop-Boks.csv'.

If your app starts fine but you don’t get any data, it could be that you added a value that was too long for the character limit of its field. If you think this might have happened, scan your console output for a message like this one:

ChangeSet 2 as cancelled: Provided value of element 'descr' exceeds maximum length of 1000 (service 'PersistenceService$Default', event 'CREATE', entity 'toadslop.bookshop.Books')

If that happened, for now just change the character limit or cut down on the characters you tried to submit. In a later tutorial we’ll learn how to handle validations to prevent this kind of error.

Step 2: API Settings

If you startup the bookshop example provided by SAP, you might notice some differences between the URL at which their API is served and the one we made. Let’s compare them.

api/browse/Books (SAP’s CAP Java example)
odata/v4/CatalogService/Books

Notice that SAP’s example starts with “api” rather than our default “odata/v4”, and also that their CatalogService displays as “browse”. This is because our app is displaying CAP’s default settings — by default all APIs are oData v4 APIs, so it labels them under that namespace, and then it exposes the services under the same name used in the CDS file. This is all fine, but sometimes we want to use something else other than those defaults. Let’s learn how.

First, changing “odata/v4” to “api”. This is an application-wide setting and so is controlled by a file called application.yml, which you’ll find in the folder srv/src/main/resources/. If you already have experience with Spring-Boot you should be familiar with this file as it’s the standard config file for a Spring-Boot application (CAP Java is built on top of Spring-Boot). Let’s open the file and take a look inside.

Interesting! Notice that we already have a default profile (for you former Node programmers, think of it as your dev environment) with a database already configured — an in-memory SQLite database. This is why we were able to seed the database with mock data in the previous step without having to configure anything first.

Anyway, to change our “odata/v4” to “api”, simply add the following code at the bottom of the file:

cds:
odata-v4.endpoint.path: "/api"

If you want to know more about the configurations you can add here, check out this documentation.

Let’s boot up the app again and see the result!

Half done! Next we need to change the way our CatalogService displays in the URL. Open up cat-service.cds and add the following annotation to our service definition:

@path : 'browse'
service CatalogService {
entity Books as projection on bookshop.Books;
}

It’s as simple as that. Let’s check the results:

We did it!

Step 3: Getting Ready to Serve UIs

Now that we have some data, it’d be nice to serve it in a UI rather than a simple JSON file. Of course we can just make any UI and make an AJAX call to the endpoint that we just made, but in this tutorial we’re going to go full SAP and show you how to setup Fiori Elements. Before we do that we need to add some additional settings to make our lives as developers easier — that’s to say, we need to configure our Spring-Boot backend to serve our UI files while we’re in development mode. In production, our UI will be deployed as a separate app so it won’t actually be served by our production backend, but in development it would be annoying to have to spin up a completely different server every time we want to test the UI. Unfortunately this doesn’t come pre-configured, but it’s not hard to set up. Let’s learn how.

First, let’s make a folder to hold our UI and an html file to test whether we can access documents in this folder or not. First, in the root directory create a folder called app, which by convention is where CAP UIs are stored; in practice you can name this whatever you want. Next create a file called fiori.html and put the following content in it:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Bookshop</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

You might ask why we called the html file fiori and not index. The reason is that CAP’s default UI for testing our backend, which we saw in Part 1 of this series, is called index.html, so if we name our file that we’ll no longer be able to access it.

Now try booting up your app and opening the file in the browser. You’ll notice that we can’t open it. This is because our Spring-Boot backend doesn’t know about the app folder.

Open up the application.yml file and add this to the top, right under spring:

web.resources.static-locations: "file:./app"

This line, not surprisingly, tells Spring where the static files are. However, if you try to open index.html you still can’t load the file. This is because the Spring app lives in the srv folder, so by default it assumes that its root folder is srv, meaning that it’s looking for the app folder there, not one level up. We need to make sure the app knows it needs to look there instead.

Open the POM.xml file in the srv folder and find the section headed by the comment <!--SPRING BOOT PLUGIN -->. Below it, locate the <configuration> tag and add the following code inside it:

<workingDirectory>..</workingDirectory>

The two dots inside this workingDirectory tag simply tell Spring-Boot that the root of the app is one folder up from the srv folder. Now it should be able to find our app folder and the index.html inside. Let’s try it. Reboot your application and click the link below:

http://localhost:8080/index.html

And, oh, look at that!

CAP wants us to login. By default, it won’t let you access the UI without logging in. Unfortunately for us, we haven’t set up any mock users so we’re stuck here. In the next section I’ll show you how to set up your mock users so you can log in and display your fiori.html file.

Step 4: Creating Mock Users

Luckily, creating our mock users is very simple. Just open up the application.yml file again and add the following line under the cds: heading:

security.mock.users:

Below that, as you can see in the picture above, you can create a set of users with various attributes. For our purposes we’ll just make two users, an admin and a regular user. Note how we provide the role admin to the admin user. We won’t be using this right away but keep it in mind as such roles allow us to fine-tune what different users are allowed to see and do in our app. In addition to these properties there are quite a few others we can use to configure our users; check them out here.

Now, let’s try to test out the UI again. Restart your server and try going to http://localhost:8080/fiori.html one more time. Enter in the username and password for one of our two users and see the result — we can successfully display our fiori.html file.

Conclusion

This brings us to the end of Part 2 of the Complete CAP Java Tutorial. To recap, we learned how to set up CSV files to seed mock data to our database when we start up the app, how to configure our API’s URL and how to assign a custom endpoint for a service using CDS. We also configured our dev backend to serve static file from a specific folder so we don’t need two servers separate servers to handle backend and frontend, and we also learned how to set up mock users.

In next week’s installment we’ll take a deep dive into configuring Fiori Elements pages from scratch.

Was anything unclear in this tutorial? Leave a question below and I’ll get back to you as soon as possible. Was anything incorrect? Please leave a comment below and let me know (a source for the correction would be most helpful). Thanks for your comments!

Support

Did you like this blog? Want to make sure I can keep creating them? Then consider subscribing on Patreon!

--

--

Brian Heise
Nerd For Tech

Full Stack web developer employed at Liferay Japan