1. Overview

Deploying a Spring Boot application to Cloud Foundry is a simple exercise. In this tutorial, we’ll show you how to do it.

2. Spring Cloud Dependencies

Since this project will require new dependencies for Spring Cloud project, we’ll add the Spring Cloud Dependencies BOM:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2023.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

We can find the latest version of the spring-cloud-dependencies library on Maven Central.

Now, we want to maintain a separate build for the Cloud Foundry, so we’ll create a profile named cloudfoundry in the Maven pom.xml.

We’ll also add compiler exclusions and the Spring Boot plugin to configure the name of the package:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <exclude>**/logback.xml</exclude>
            </excludes>
        </resource>
    </resources>
    <plugins>
        <plugin>                        
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <finalName>${project.name}-cf</finalName>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>**/cloud/config/*.java</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

We also want to exclude the cloud-specific files from the normal build so we add a global profile exclusion to Maven compiler plugin:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>**/cloud/*.java</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

Then, we need to add the Spring Cloud Starter and the Spring Cloud Connectors libraries, which provide support for Cloud Foundry:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cloud-connectors</artifactId>
</dependency>

3. Cloud Foundry Configuration

To go through this tutorial, we need to register for a trial here or download the pre-configured development environment for Native Linux or Virtual Box.

Furthermore, the Cloud Foundry CLI needs to be installed. Instructions are here.

After registration with a Cloud Foundry provider, the API URL will be made available (you can come back to it by following the Tools option on the left side).

The application container allows us to bind services to applications. Next, let’s log in to the Cloud Foundry environment:

cf login -a <url>

The Cloud Foundry Marketplace is a catalog of services like databases, messaging, email, monitoring, logging and a lot more. Most services provide a free or trial plan.

Let’s search the Marketplace for “MySQL” and create a service for our application:

cf marketplace | grep MySQL
>
cleardb     spark, boost*, amp*, shock*         Highly available MySQL for your Apps.

The output lists the services with “MySQL” in the description. On PCF the MySQL service is named cleardb and non-free plans are marked with an asterisk.

Next, we list the details of a service using:

cf marketplace -s cleardb
>
service plan description                                                                 free or paid
spark        Great for getting started and developing your apps                             free
boost        Best for light production or staging your applications                         paid
amp          For apps with moderate data requirements                                       paid
shock        Designed for apps where you need real MySQL reliability, power and throughput  paid

Now we create a free MySQL service instance named spring-bootstrap-db:

cf create-service cleardb spark spring-bootstrap-db

4. Application Configuration

Next, we add a @Configuration annotated class that extends AbstractCloudConfig to create a DataSource in the package named org.baeldung.cloud.config:

@Configuration
@Profile("cloud")
public class CloudDataSourceConfig extends AbstractCloudConfig {
 
    @Bean
    public DataSource dataSource() {
        return connectionFactory().dataSource();
    }
}

Adding @Profile(“cloud”) ensures that the Cloud Connector isn’t active when we do local testing. We also add @ActiveProfiles(profiles = {“local”}) to the Integration tests.

Then build the application with:

mvn clean install spring-boot:repackage -P cloudfoundry

Also, we need to provide a manifest.yml file, to bind the service to the application.

We usually place the manifest.yml file in the project folder but in this case, we’ll create a cloudfoundry folder since we’re going to demonstrate deploying to multiple cloud-native providers:

---
applications:
- name: spring-boot-bootstrap
  memory: 768M
  random-route: true
  path: ../target/spring-boot-bootstrap-cf.jar
  env:
    SPRING_PROFILES_ACTIVE: cloud,mysql
  services:
  - spring-bootstrap-db

5. Deployment

Deploying the application is now as easy as:

cd cloudfoundry
cf push

Cloud Foundry will use the Java buildpack to deploy the application and create a random route to the application.

We can view the last few entries in the log file using:

cf logs spring-boot-bootstrap --recent

Or we can tail the log file:

cf logs spring-boot-bootstrap

Finally, we need the route name to test the application:

cf app spring-boot-bootstrap
>
name:              spring-boot-bootstrap
requested state:   started
routes:            spring-boot-bootstrap-delightful-chimpanzee.cfapps.io
last uploaded:     Thu 23 Aug 08:57:20 SAST 2018
stack:             cflinuxfs2
buildpacks:        java-buildpack=v4.15-offline-...

type:           web
instances:      1/1
memory usage:   768M
     state     since                  cpu    memory           disk
#0   running   2018-08-23T06:57:57Z   0.5%   290.9M of 768M   164.7M of 1G

Executing the following command will add a new book:

curl -i --request POST \
    --header "Content-Type: application/json" \
    --data '{"title": "The Player of Games", "author": "Iain M. Banks"}' \
    https://<app-route>/api/books
#OR
http POST https://<app-route>/api/books title="The Player of Games" author="Iain M. Banks"

And this command will list all books:

curl -i https://<app-route>/api/books 
#OR 
http https://<app-route>/api/books
>
HTTP/1.1 200 OK

[
    {
        "author": "Iain M. Banks",
        "id": 1,
        "title": "Player of Games"
    },
    {
        "author": "J.R.R. Tolkien",
        "id": 2,
        "title": "The Hobbit"
    }
]

6. Scaling the Application

Lastly, scaling an application on Cloud Foundry is as simple as using the scale command:

cf scale spring-cloud-bootstrap-cloudfoundry <options>
Options:
-i <instances>
-m <memory-allocated> # Like 512M or 1G
-k <disk-space-allocated> # Like 1G or 2G
-f # Force restart without prompt

Remember to delete the application when we don’t need it anymore:

cf delete spring-cloud-bootstrap-cloudfoundry

7. Conclusion

In this article, we covered the Spring Cloud libraries that simplify the development of a cloud-native application using Spring Boot. Deployment with the Cloud Foundry CLI is well documented here.

Extra plugins for the CLI are available in the plugin repository.

The full source code of our examples here is, as always, over on GitHub.