How to run a simple Spring Boot RESTful service on SAP Cloud Platform
The following short tutorial shows how to run a simple Spring Boot RESTful service on SAP Cloud Platform. The application was created as part of this year’s SAP Community Open Space Hack Session during the SAP Inside Track Munich (#sitmuc).
About Spring Boot
Spring Boot allows you to quickly setup and run production-ready Spring based Java applications. With only a little configuration you are able to run different scenarios such as RESTful services, JPA-backed persistence, etc. For more on Spring Boot continue here.
Sample application
Our sample application currently supports one GET operation to
/test-api/products
returning a JSON array of three different products.
You may retrieve the code from the GitHub repository https://github.com/pliegl/sample-rest-product-service
Application walkthrough
You only need four artifacts to get your application up an running. We use Maven to take care of the project dependencies.
pom.xml
The necessary dependencies are configured in pom.xml. We are using two different profiles – one to run the application standalone on the local machine and one for running it in a Tomcat 8 on SAP Cloud platform.
<profiles>
<!-- Used to run the app on the local machine as standalone application -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</profile>
<!-- Used to run the app on SAP Cloud Platform in a Tomcat 8 -->
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</exclusion>
<!-- Exclude logback and SpringBoot logging, otherwise the app won't start on SAP Cloud Platform -->
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
SpringRestApplication.java
Our main class. The @SpringBootApplication and @ComponentScan annotations are sufficient to let Spring Boot know, what to do. Please note that we must extend SpringBootServletInitializer in order to let the application work within Tomcat.
* Sample RESTful application
*/
@SpringBootApplication
@ComponentScan("com.ecosio")
public class SpringRestApplication extends SpringBootServletInitializer {
//Make sure that everything for .war deployment is there
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringRestApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringRestApplication.class, args);
}
}
Product.java
Defines the structure of our products. We use Lombok to autogenerate getters and setter on a byte code level.
/**
* Sample product structure. Note that getters and setter are auto-generated by Lombok
*/
@Data
@Builder
public class Product {
private String id;
private String name;
private BigDecimal price;
}
ProductController.java
Defines our REST API. Currently, a single GET method is supported. Additional operations such as POST, PUT, etc. may easily be added using the pertinent annotations and respective methods.
/**
* Serves a list of sample products
*/
@RestController
@RequestMapping("/test-api")
public class ProductController {
private List<Product> products = new LinkedList<>();
@RequestMapping(method = RequestMethod.GET, value = "/products")
public List<Product> getProducts () {
return products;
}
@PostConstruct
private void loadDummyData() {
products.add(Product.builder().id("1").name("Apple").price(new BigDecimal("0.7")).build());
products.add(Product.builder().id("2").name("Pear").price(new BigDecimal("0.8")).build());
products.add(Product.builder().id("3").name("Orange").price(new BigDecimal("0.4")).build());
}
}
With these four Java/XML artifacts we are ready to go.
Running the application
To run the application locally, run the following command on the command line:
mvn spring-boot:run
To prepare the artifacts for deployment on SAP Cloud platform, run the following command on the command line
mvn -P prod clean package
The final artifact sample-rest-product-service.war may be found in the /target folder.
Deploying it on SAP Cloud Platform
- Login to SAP Cloud Platform on https://account.hanatrial.ondemand.com
- Chose JAVA Applications and then Deploy Application
- Select the previously generated sample-rest-product-service.war file and provide a name for your application. Select Java Web Tomcat 8 as runtime. Leave all other parameters unchanged.
- Check the status of your application
- In order to view the result of the GET request, click on the link as outlined below
The link shall look as follows:
https://samplerestprodupXXXtria.hanatrial.ondemand.com/sample-rest-product-service/test-api/products
whereby XXX is specific to your SAP cloud platform account. Use a tool like Postman, to access the RESTful service. A regular Web browser will do as well for the simple GET request.
Summary
With only a few Java classes and clicks you are ready to deploy your first RESTful app to SAP Cloud Platform.
Hi Philipp,
I am trying a similar scenario and getting 404 status for the application in started state. I have extended SpringBootServletInitializer in my application as well. Could you please help ?
Thanks
Hi Apurva,
In order to provide a helpful answer, please provide more details. A 404 indicates, that the client is unable to retrieve an answer from the server, because the target on the server cannot be found. This is usually due to an application which did not start. I would start with investigating the server logs.
Philipp
Is there any example springboot app accessing hana database using hanatrial environment ?
Thanks a lot, this really helped me!