Create an Application with SAP Java Buildpack
- How to create a Spring Boot Java project
- How to create and deploy a simple “Hello World” application
- How to run authentication and authorization checks via the XSUAA service
Prerequisites
- You have a trial or productive account for SAP Business Technology Platform (SAP BTP). If you don’t have such yet, you can create one so you can try out services for free
- You have created a subaccount and a space on Cloud Foundry Environment
- cf CLI is installed locally
- You have downloaded
JDK for SapMachine 11
and installed it locally, configuring yourPATH
andJAVA_HOME
environment variables - You have Apache Maven downloaded. To do that, go to Files and choose the
Binary zip archive
link. For this tutorial, we use version3.8.5
- Install Maven - similar to JDK, configure your
PATH
andMAVEN_HOME
variables - You have downloaded and installed Eclipse IDE for Enterprise Java and Web Developers
This tutorial will guide you through creating and setting up a simple Java application by using cf CLI. You will start by creating a Java project via Spring Boot, and then creating a web application that returns simple data – a Hello World! message. This simple app will be invoked through a web microservice (application router). Finally, you will set authentication checks and an authorization role to properly access your web application.
- Step 1
First, you need to connect to the SAP BTP, Cloud Foundry environment with your productive subaccount. Your Cloud Foundry URL depends on the region where the API endpoint belongs to. To find out which one is yours, see: Regions and API Endpoints Available for the CF Environment
In this tutorial, we use
eu20.hana.ondemand.com
as an example.-
Open a command-line console.
-
Set the Cloud Foundry API endpoint for your subaccount. Execute (using your actual region URL):
Bash/ShellCopycf api https://api.cf.eu20.hana.ondemand.com
- Log in to SAP BTP, Cloud Foundry environment: Bash/ShellCopy
cf login
-
When prompted, enter your user credentials – the email and password you have used to register your productive SAP BTP account.
IMPORTANT: If the authentication fails, even though you’ve entered correct credentials, try logging in via single sign-on.
-
Choose the org name and space where you want to create your application.
If you’re using a trial account, you don’t need to choose anything. You can use only one org name, and your default space is
dev
.
RESULT
Details about your personal SAP BTP subaccount are displayed (API endpoint, user, organization, space).
Which file contains information about the buildpack that provides the runtime on which you deploy your application?
Log in to complete tutorial -
- Step 2
Before creating an application, you need a Java project. For this tutorial, you can easily create one by using Spring Boot.
Open:
https://start.spring.io
From the configuration screen, choose
Maven Project
, languageJava
, and Spring Boot version2.7.0
.From
Project Metadata
section, you need to do the following settings:Group:
com.example
Artifact:
java-tutorial
Name:
HelloWorld
Description:
A simple HelloWorld Java project
Package name:
com.example.java-tutorial
Packaging:
Jar
Java:
8
Choose
Add Dependencies
and then selectSpring Web
.Choose
Generate
.A
java-tutorial.zip
file is generated. Save it on your local file system and then extract thejava-tutorial
folder.
RESULT
You have successfully created a basic Java project.
Log in to complete tutorial - Step 3
For this part, you need to configure your
HelloWorld
application, add an extra class, and amanifest.yml
file.Open
java-tutorial
directory in a console client, and execute:Bash/ShellCopymvn install
This command builds your Java project (as a Maven one).
Go back to the
java-tutorial
folder and create a filemanifest.yml
with the following content (using your ACTUALL path!):YAMLCopy--- applications: - name: helloworld random-route: true path: ./target/java-tutorial-0.0.1-SNAPSHOT.jar memory: 1024M buildpack: sap_java_buildpack env: TARGET_RUNTIME: tomcat JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jdk.SAPMachineJDK']"
Now open your Eclipse IDE, in the
Java
perspective.Choose
File
>Open Projects from File System
, and browse to yourjava-tutorial
folder.Select
Add project to working sets
and chooseFinish
.Your
java-tutorial
project is populated in theProject Explorer
.Navigate to
src\main\java\com.example.javatutorial
and double-click onHelloWorldApplication.java
.In the
public static void main
class, add the following line:System.out.println("Hello World!");
Your final Java code should look like this:
JavaCopy
package com.example.javatutorial; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class HelloWorldApplication { public static void main(String[] args) { SpringApplication.run(HelloWorldApplication.class, args); System.out.println("Hello World!"); } }Navigate to
src/main/java
and go to thecom.example.javatutorial
package.From its context menu, choose
New
>Class
.Enter
MainController
as the name of the Java class and chooseFinish
. The new class appears in the project navigation.Open the
MainController.java
file and replace its default content with the following code:JavaCopy
package com.example.javatutorial; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(path = "") public class MainController { @GetMapping(path = "") public ResponseEntity<String> getDroneMedications() { return new ResponseEntity<String>("Hello World!", HttpStatus.OK); } }
RESULT
Your Java project is complete and your application is ready to be deployed.
- Step 4
You are in the Eclipse IDE.
Test your project locally. To do that, right-click on
HelloworldApplication.java
and chooseRun As
>Java Application
.The final result displayed in the
Console
tab should be: Hello World!Same result will be displayed in a browser if you enter:
localhost:8080
Now go to the
java-tutorial
directory and build your project again, by executing:Bash/ShellCopymvn clean install
Then execute:
Bash/ShellCopycf push
This command deploys your Java application.
Make sure you always execute
cf push
in the folder where themanifest.yml
file is located! In this case, that’sjava-tutorial
.When the staging and deployment steps are completed, the
helloworld
application should be successfully started and its details displayed in the command console.Now open a browser window and enter the generated URL of the
helloworld
application (seeroutes
).
For example:
https://helloworld-noway-panda.cfapps.eu20.hana.ondemand.com
RESULT
Your Java application is successfully deployed and running on the SAP BTP, Cloud Foundry environment. A Hello World! message is displayed in the browser.
- Step 5
Authentication in the SAP BTP, Cloud Foundry environment is provided by the Authorization and Trust Management (XSUAA) service. In this example, OAuth 2.0 is used as the authentication mechanism. The simplest way to add authentication is to use the Node.js
@sap/approuter
package. To do that, a separate Node.js micro-service will be created, acting as an entry point for the application.In the
java-tutorial
folder, create anxs-security.json
file for your application with the following content:JSONCopy{ "xsappname" : "helloworld", "tenant-mode" : "dedicated" }
IMPORTANT: For trial accounts, enter the following additional
oauth2-configuration
code in yourxs-security.json
file:JSONCopy{ "xsappname" : "helloworld", "tenant-mode" : "dedicated", "oauth2-configuration": { "redirect-uris": [ "https://*.cfapps.eu20.hana.ondemand.com/**" ] } }
Create an
xsuaa
service instance namedjavauaa
with planapplication
. To do that, execute the following command in thejava-tutorial
directory:Bash/ShellCopycf create-service xsuaa application javauaa -c xs-security.json
Add the
javauaa
service inmanifest.yml
so the file looks like this:YAMLCopy--- applications: - name: helloworld random-route: true path: ./target/java-tutorial-0.0.1-SNAPSHOT.jar memory: 1024M buildpack: sap_java_buildpack env: TARGET_RUNTIME: tomcat JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jdk.SAPMachineJDK']" services: - javauaa
The
javauaa
service instance will be bound to thehelloworld
application during deployment.Now you have to create a microservice (the application router). Go to the
java-tutorial
folder and create a subfolderweb
.IMPORTANT: Make sure you don’t have another application with the name
web
in your space! If you do, use a different name and adjust the rest of the tutorial according to it.Inside the
web
folder, create a subfolderresources
. This folder will provide the business application’s static resources.Inside the
resources
folder, create anindex.html
file with the following content:HTMLCopy<html> <head> <title>Java Tutorial</title> </head> <body> <h1>Java Tutorial</h1> <a href="/helloworld/">My Java Application</a> </body> </html>
This will be the start page of the
helloworld
application.In the
web
directory, execute:Bash/ShellCopynpm init
Press Enter on every step. This process will walk you through creating a
package.json
file in theweb
folder.Now you need to create a directory
web/node_modules/@sap
and install anapprouter
package in it. To do that, in theweb
directory execute:Bash/ShellCopynpm install @sap/approuter --save
In the
web
folder, open thepackage.json
file and replace the scripts section with the following:JSONCopy"scripts": { "start": "node node_modules/@sap/approuter/approuter.js" },
Now you need to add the
web
application to your project and bind the XSUAA service instance (javauaa
) to it. To do that, insert the following content at the end of yourmanifest.yml
file.YAMLCopy- name: web random-route: true path: web memory: 1024M env: destinations: > [ { "name":"helloworld", "url":"https://helloworld-noway-panda.cfapps.eu20.hana.ondemand.com/", "forwardAuthToken": true } ] services: - javauaa
For the
url
value, enter your generated URL for themyapp
applicationIn the
web
folder, create anxs-app.json
file with the following content:JSONCopy{ "routes": [ { "source": "^/helloworld/(.*)$", "target": "$1", "destination": "helloworld" } ] }
With this configuration, the incoming request is forwarded to the
helloworld
application, configured as a destination. By default, every route requires OAuth authentication, so the requests to this path will require an authenticated user.Open your
pom.xml
file and replace the entire<dependencies>
block with the following:XMLCopy<dependencies> <!-- Spring Boot starter packages --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cloud-connectors</artifactId> <version>2.2.13.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring and XSUAA Security --> <dependency> <groupId>com.sap.cloud.security.xsuaa</groupId> <artifactId>xsuaa-spring-boot-starter</artifactId> <version>2.12.2</version> </dependency> <!-- dependencies for test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Now go to the
java-tutorial
directory and execute:Bash/ShellCopymvn clean install
Then execute:
Bash/ShellCopycf push
This command will update the
helloworld
application and deploy theweb
application.What’s going on?
As of this point of the tutorial, the URL of the
web
application will be requested instead of thehelloworld
URL. It will then forward the requests to thehelloworld
application.When the staging and deployment steps are completed, the
web
application should be successfully started and its details displayed in the command console.Open a new browser tab or window, and enter the generated URL of the
web
application.For example:
https://web-thankfully-fox.cfapps.eu20.hana.ondemand.com
Enter the credentials for your SAP BTP user.
RESULT
A simple page with title
Java Tutorial
is displayed. When you click theMy Application
link, the output of yourhelloworld
application is displayed.Check that the
helloworld
application is not directly accessible without authentication. To do that, refresh its previously loaded URL in a web browser – you should get a response401 Unauthorized
.
- Step 6
Authorization in the SAP BTP, Cloud Foundry environment is also provided by the XSUAA service. In the previous example, the
@sap/approuter
package was added to provide a central entry point for the business application and to enable authentication. Now to extend the example, authorization will be added.Navigate to
src/main/java
and go to thecom.example.javatutorial
package.From its context menu, choose
New
>Class
.Enter
WebSecurityConfig.java
as the name of the Java class and chooseFinish
. The new class appears in the project navigation.Open the
WebSecurityConfig.java
file and replace its content with the following code:JavaCopypackage com.example.javatutorial; import com.sap.cloud.security.xsuaa.XsuaaServiceConfiguration; import com.sap.cloud.security.xsuaa.token.TokenAuthenticationConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.web.SecurityFilterChain; @Configuration public class WebSecurityConfig { @Autowired XsuaaServiceConfiguration xsuaaServiceConfiguration; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .sessionManagement() // session is created by approuter .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() // demand specific scopes depending on intended request .authorizeRequests() .antMatchers("/**").authenticated() .anyRequest().denyAll() // deny anything not configured above .and() .oauth2ResourceServer().jwt() .jwtAuthenticationConverter(getJwtAuthoritiesConverter()); return http.build(); } /** * Customizes how GrantedAuthority are derived from a Jwt * * @returns jwt converter */ Converter<Jwt, AbstractAuthenticationToken> getJwtAuthoritiesConverter() { TokenAuthenticationConverter converter = new TokenAuthenticationConverter(xsuaaServiceConfiguration); converter.setLocalScopeAsAuthorities(true); return converter; } }
In the same way, create another Java class, named
NotAuthorizedException.java
, and replace its content with:JavaCopypackage com.example.javatutorial; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @SuppressWarnings("serial") @ResponseStatus(HttpStatus.FORBIDDEN) public class NotAuthorizedException extends RuntimeException { public NotAuthorizedException(String message) { super(message); } }
Open the
MainController.java
file and replace its content with the following:JavaCopypackage com.example.javatutorial; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.security.core.annotation.AuthenticationPrincipal; import com.sap.cloud.security.xsuaa.token.Token; @RestController @RequestMapping(path = "") public class MainController { @GetMapping(path = "") public ResponseEntity<String> readAll(@AuthenticationPrincipal Token token) { if (!token.getAuthorities().contains(new SimpleGrantedAuthority("Display"))) { throw new NotAuthorizedException("This operation requires \"Display\" scope"); } return new ResponseEntity<String>("Hello World!", HttpStatus.OK); } }
To introduce an application role, open the
xs-security.json
in thejava-tutorial
folder, and add the necessary scopeDisplay
and role templateViewer
, as follows:JSONCopy{ "xsappname": "helloworld", "tenant-mode": "dedicated", "scopes": [ { "name": "$XSAPPNAME.Display", "description": "Display content" } ], "role-templates": [ { "name": "Viewer", "description": "View content", "scope-references": [ "$XSAPPNAME.Display" ] } ] }
For trial accounts, adjust the code with the
oauth2-configuration
part.Update the XSUAA service. To do that, in the
java-tutorial
directory execute:Bash/ShellCopycf update-service javauaa -c xs-security.json
Then build your project, by executing:
Bash/ShellCopymvn clean install
And finally, execute:
Bash/ShellCopycf push helloworld
This command will redeploy only the
helloworld
application. No changes have been made inweb
so no need to redeploy it.Try to access
helloworld
again (in a browser) in both ways – directly, and through theweb
application router.
RESULT
If you try to access it directly, a
401 Unauthorized
response is still displayed due to lack of authorization token (expected behavior).If you try to access it through the app router, it results in a
403 Forbidden
response due to missing permissions. To get these permissions, you need to create a role collection containing the roleViewer
and assign this role to your user. You can do this only from the SAP BTP cockpit.
Log in to complete tutorial - Step 7
Open the SAP BTP cockpit and go to your subaccount.
From the left-side menu, navigate to
Security
>Role Collections
.Create a new role collection. For example,
MyJavaAppRC
.Click this role collection and then choose
Edit
.In the
Roles
tab, click theRole Name
field.Type Viewer. From the displayed results, select the
Viewer
role that corresponds to your application, and chooseAdd
.Now go to the
Users
tab, and in theID
field, enter your e-mail. Then enter the same e-mail in theE-Mail
field.Save your changes.
Your role collection is now assigned to your user and contains the role you need to view the content of your application.
Now you need to apply these changes to the
helloworld
application by building and redeploying it again.Go back to the command line, and in the
java-tutorial
directory, execute:Bash/ShellCopymvn clean install
And finally, execute:
Bash/ShellCopycf push helloworld
RESULT
When you try to access again the
helloworld
application through the app router, it will successfully display the Hello World! message.In order for the new result to take effect immediately, you might need to clear the cache of your browser. Or just open the
web
application URL in a private/incognito browser tab.Log in to complete tutorial