---
title: "REST API development with Spring Boot and Platform Tools"
canonical: "https://onesaitplatform.refined.site/space/DOCT/2221616312/REST%20API%20development%20with%20Spring%20Boot%20and%20Platform%20Tools"
format: markdown
---
> Macro (toc)

### Introduction

This article will show the development lifecycle using Spring Boot as the base technology for building the API. This API will be connected against a MongoDB instance and deployed as a Docker container on the CaaS platform included in Onesait Platofmr.

Platform services, such as Identity Manager, API Manager, and microservices deployment support, will be used to speed this up.

> ℹ️ INFO
> ℹ️ 
> ℹ️ The code for this example is available in this Github repository: [https://github.com/onesaitplatform/onesaitplatform-spring-boot-example](https://github.com/onesaitplatform/onesaitplatform-spring-boot-example) .

### Preparing the Development Environment

The API we are going to develop is based on these technologies:

- Java 8 (or higher) as the base technology for development.
- Spring Boot 2 as the development framework.
- MongoDB as the NoSQL database to store the data.
- Eclipse as the IDE.
- Maven as the project construction tool.
- JUnit as the test technology.

> ℹ️ Onesait Platform offers an SDK for Windows that integrates all these pieces, so that a developer doesn't have to install them on their own.
> ℹ️ 
> ℹ️ You can see how to install it in this post: [How to run the platform in my Windows PC with OP-SDK?](https://onesaitplatform.atlassian.net/wiki/spaces/OP/pages/7897242)

## API development with Spring Boot

### Creating your application's skeleton

The easiest way to start a Spring Boot application is to access the Spring Initializr website ([https://start.spring.io](https://start.spring.io)) and configure the settings of your Spring Boot application:

![image](media://00bc4c8a-1077-4fac-82c5-39afe9f5fe77)

You will use MongoDB as a NoSQL database for data storage and Spring Data to work on top of Mongo, and Spring Web to create the REST API.

To work with Mongo, you will need a Mongo instance to work on, either containerised or installed in your local environment.

Once you have it launched, configure it in the application.yml of your Spring Boot application.

![image](media://be9c9725-c3b0-4edc-984c-1fbfa82c9fb8)

### Creating the Message entity

For starters, create the **Message **entity as the class that represents the document in MongoDB. To do this, use the @Document annotation and mark the idMessage field as @Id.

Para empezar crearemos la entidad **Message **como clase que representa el documento en MongoDB, para ello haremos uso de la anotación @Document , y marcaremos el campo idMessage como @Id 

![image](media://12015f9f-cb0b-41e3-a408-c566f5eb0fdd)

### Creating the repositories

Spring Data MongoDB comes with a set of methods for queries that it implements underneath, but for more complex queries, such as grouping by state, you will need to implement the method.

**MessageRepository**

In this class, you will extend both MongoRepository and your custom repository, where the custom operations to implement will go:

![image](media://88e8f96c-c2fe-494f-9c93-73497c62766a)

**MessageRepositoryCustom**

As we said, here are the definitions of the custom operations:

![image](media://85fca2b3-64db-4cd7-a7da-1cb06e59a554)

As you can see, two new classes appear as the return methods: TypeAggregationResults and StatusAggregationResults. These are DTOs to map the result of the queries, because obviously no Message structure is returned for grouping queries.

![image](media://731e4f11-43d4-48d1-aeda-cd3a8bc60ea8)

![image](media://fc605219-8e50-4962-a217-c740a8feb221)

The DTO also has the percentage field to be able to return the result with %.

**MessageRepositoryImpl**

Here you will implement the methods defined in the interface. Bear in mind that the class must be called as the MessageRepository interface (which extends MongoRepository) + "Impl", so that the Spring Data MongoDB autoconfiguration works correctly.

![image](media://9626c32f-6a10-4870-b13f-0b41a4789508)

![image](media://81752edb-2a40-45f9-8dc5-37e2bc0a3c4d)

As you can see, in the grouping operations by state and type, you have to use MongoDB's Aggregations, and also use projections.

### Service layer

A service layer will be needed to orchestrate the calls to the repository.

**MessageService**

![image](media://8b3f378b-465f-4d71-a2f2-c3e27b3dea97)

**MessageServiceImpl**

Here you will implement the methods (see code).

### Controller and documentation with Swagger

Finally, to finish the API, you will need to define the controller layer and document it with Swagger:

![image](media://fbd2b9c6-ac3c-46db-960b-474570ddd559)

In the implementation of this controller, you will make use of the service described before, MessageService (see code).

### Enable Swagger interface

You will need to add the Swagger dependencies to your project to be able to use these features.

To be able to access the Swagger interface of the application, you will have to enable Swagger 2, and configure your API.

**SwaggerConfig**

![image](media://2b533800-9b7a-4c70-9c6d-9706b3726369)

With this, you will be able to access your API when you launch the Spring Boot App:

![image](media://93aa48f4-f4f6-44a6-98b1-7174eac67b04)


![image](media://e0b1dab2-cf54-4645-a829-b5a15281d51e)

### API functionality: sending mails

To use the Spring mail service, you have to include the **spring-boot-starter-mail **dependency in the project, and configure the properties in the application.yml:

![image](media://7707499f-dcfe-4f9f-8c2b-a4b5b7abb770)

Then you will create a service for sending mails.

**MailServiceImpl**

![image](media://9a41d273-30ee-4c50-8484-e8b28e0ed527)

Now, modify the method for creating new Messages, in the MessageServiceImpl, so that when a new message is created, and it is of type Mail, it will send a mail. If everything goes well, its status will be updated to SENT; otherwise, the status is left as wrong.

![image](media://dda626c0-3ba2-49d1-a704-94ef2d54c83e)

### <u>Integrating security to your API: authentication</u>

To control who invokes your API, integrate it with the Platform Identity Manager, so that no additional parts are needed. The platform offers a library to simplify its use; make use of it:  [https://onesaitplatform.atlassian.net/wiki/spaces/PT/pages/180682753](https://onesaitplatform.atlassian.net/wiki/spaces/PT/pages/180682753) 

As you won't use Realms in this example, you can leave the configuration as is:

![image](media://5dacf17d-3c16-4d1e-834e-8c4b047131f7)

Create another REST service to log in the users of your application:

![image](media://01690a08-c645-4170-9e64-7b49d8630a35)

![image](media://8885b283-0ca4-48e1-b895-7b05037afe10)

In this endpoint, users will be able to get their Oauth2 token in order to use it for Message API calls.

You will have to add another Docket to the Swagger configuration to document this authentication API:

![image](media://2b6b952f-f11c-4cbd-a318-cbef8adda52e)

And for the Message API, you will have to mandatorily add the Authentication header to all operations:

![image](media://312a1b2d-8faf-4266-afe9-880b067fc61b)

Lastly, you will have to configure the security, so that all the /api/message** paths are secured by the library:

![image](media://b45e7a5b-7b9f-472a-b9c6-a91ff3c7971e)

Now you have your Message API secured.

![image](media://abf043b1-893f-4e8b-af44-411a3cdcfb93)

![image](media://0256f03d-d40b-4fec-9811-cfeb80cd4b30)

And you can see how the status is updated once the email has been sent:

```
 {
    "idMessage": "90-90lkn-78-fhde",
    "txtMessage": "NEW MESSAGE TEST",
    "typeMessage": "MAIL",
    "fromMessage": null,
    "toMessage": "fjgcornejo@minsait.com",
    "statusMessage": "SENT",
    "sentDate": "2020-05-13T14:54:47.389+0000",
    "errorOnSending": null
  }
```

![image](media://6ac7451b-9be9-4234-b5ac-104d4ed92e01)

### <u>Completing the API functionality</u>

Now you will configure the SMS sending service. You are going to use [Twilio](https://www.twilio.com/) as a messaging service, as it offers $16 free to use its services. So, sign up, and set up a number for the trial period.

Put the Twilio SDK dependency in your project:

```
<dependency>
	<groupId>com.twilio.sdk</groupId>
	<artifactId>twilio</artifactId>
	<version>7.42.0</version>
</dependency>
```

In the configuration properties, you will need:

![image](media://5845776a-b5cd-4aa0-9e9c-9d1715bc9b99)

Create the service with a simple method that sends messages.

![image](media://570da7d5-335a-467d-87f3-44b3e305c291)

Finally, modify the MessageServiceImpl service so that when it is an SMS message, it uses the service you just created:

![image](media://80151026-c58d-4754-8965-df2a3e67ab0d)

Now you will test the service from Swagger:

![image](media://03366a6a-1d05-4301-813e-650ee81f65ea)

And you can see how it sends the SMS and correctly updates the status of the Message:

![image](media://bfb5daf6-4960-485b-a839-11c123341fc0)


```
  {
    "idMessage": "789-978hjn",
    "txtMessage": "Hola esto es una prueba SMS. Irá bien",
    "typeMessage": "SMS",
    "toMessage": "+34616986373",
    "statusMessage": "SENT",
    "sentDate": "2020-05-14T09:29:26.047+0000"
  }
```

You can also force an error, so that it updates the status of the message to ERROR, for example, by setting an invalid number (+1234):

```
  {
    "idMessage": "789-978hjn",
    "txtMessage": "Hola esto es una prueba SMS. Irá mal",
    "typeMessage": "SMS",
    "toMessage": "+1234",
    "statusMessage": "ERROR",
    "sentDate": "2020-05-14T09:38:31.630+0000",
    "errorOnSent": "Could not send SMS: The 'To' number +1234 is not a valid phone number."
  }
```

### <u>Deploying your API</u>

In the case of Spring Boot development, you have to deploy the pieces that make up your local development to an environment. In this example, you will need to have a MongoDB available for storage and then deploy your API developed with Spring Boot.

There are different ways to do this depending on the environment you are working in. For the deployment of Spring Boot applications, nowadays it is standardised to deploy applications with Docker. For MongoDB there, are several ways: containerised deployment, use as a service.

The platform helps you to automate this part as the platform integrates a MongoDB among its components and allows you to deploy Spring Boot applications in a simple way on the integrated CaaS platform.

To deploy your API (Spring Boot application), you will have to dockerise it first. To do so, you will have to create a structure like the following:

- sources/
  - docker/
    - Dockerfile
  - src/main/resources
    - application-docker.yml

Then deploy the microservice on the Platform: [https://onesaitplatform.atlassian.net/wiki/spaces/PT/pages/183599130](https://onesaitplatform.atlassian.net/wiki/spaces/PT/pages/183599130) 

In the **application-docker.yml **, overwrite the properties that will change on each deployment:

```
server: ## Config Web Server
   port: ${PORT}
   servlet.contextPath: ${CONTEXT_PATH}
spring:
   data:
     mongodb:
        uri: mongodb://${MONGO_SERVER}:27017/${MONGO_DB}
   

openplatform.api:
   baseurl: https://${ONESAIT_SERVERNAME}

## LOGGING CONF
logging:
   path: /var/log 
   file: ${spring.application.name}
   level:
      com.minsait: DEBUG 
      org.springframework.security: INFO
```

The Dockerfile will look like this:

```
FROM openjdk:8-jdk-alpine

# Metadata
LABEL module.name="spring-boot-demo"	


COPY *.jar app.jar

# logs folder
RUN mkdir -p /var/log && \
	mkdir ./target


# create user
RUN addgroup -S user -g 433 && adduser -u 431 -S -g user -h /usr/local -s /sbin/nologin user

RUN  chown -R user:user /var/log && \
	 chmod -R 777 /var/log && \
	 chown user:user app.jar && \
	 chown -R user:user ./target && \    
     chmod -R 777 ./target
	 
	 
VOLUME ["/var/log"]


USER user

EXPOSE 8080


ENV JAVA_OPTS="$JAVA_OPTS -Xms1G -Xmx3G" \
	ONESAIT_SERVERNAME=development.onesaitplatform.com \
	PORT=8080 \
	CONTEXT_PATH=/spring-boot-demo \
	MONGO_SERVER=mongodb-demo \
	MONGO_DB=spring_boot_demo
	
	

ENTRYPOINT java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /app.jar


```

Once you have these files in the repository, you can proceed to create the microservice on the platform.

![image](media://fdcbe795-458b-47df-8c56-54a222336a1f)

About the Gitlab, Jenkins and Rancher configurations, if they have not been configured by the platform environment administrator, you will have to configure them ourselves, with the requested credentials.

Once created, you can generate the image that you will deploy.

![image](media://dc668ac4-09f4-42ae-a6c6-23eaf99b3cbe)

![image](media://cf55b76b-fd5d-427d-aa22-85857d44e74b)

When the generation is finished, you can proceed to deploy the microservice, but first, you must deploy a Mongo so that your application can use it.

For this, generate a stack in the CaaS Platform, and put a service with the mongo:4.0 image.

![image](media://5a24d4f6-669b-46e5-827b-7a72c4ccd5e2)

Once ready, you can deploy your microservice, in the stack you just created:

![image](media://0c3f6749-8221-49fc-b37c-9943c0ada7c0)

Now you have the service deployed in your stack:

![image](media://410b6bb2-5ba9-4e7f-ae65-9e6c41a31946)

And you can invoke it from the URL:

![image](media://a8b45ab9-f87f-46d4-b2f7-882d9332655b)

### Managing the API lifecycle from the Portal API

Although you can make use of the API from the URL indicated above, you  can publish the API as an external API in the API Manager to be able to make use of the lifecycle management that the onesait Platform does, explained here: [https://onesaitplatform.atlassian.net/wiki/spaces/OP/pages/327878/Lifecycle+of+REST+APIS+in+Platform](https://onesaitplatform.atlassian.net/wiki/spaces/OP/pages/327878/Lifecycle+of+REST+APIS+in+Platform) 

Go to APIs and create an external REST API, indicating the URL of the swagger.json of our service. This URL can be found here:

![image](media://c242783b-f2d6-419d-a8b5-2330eb52ffae)

![image](media://a92dd28c-81d8-4d03-a80c-5e9edacc364f)

Now your Spring Boot API will be managed by the API Manager, so you will be able to invoke it through it:

![image](media://64f0e6d0-32a1-4d7b-a7ae-07ecef14682d)

> ℹ️ This way the API security could be handled by the API Manager, and you could skip the security configuration with the library described in the previous section: <u>Integrating security to your API: authentication</u>