/ CLOUD FOUNDRY, MICROSERVICES, PIVOTAL, SPRING BOOT

Going the microservices way - part 2

In my previous post, I developed a simple microservices REST application based on Spring Boot in a few lines of code. Now is the time to put this application in the cloud. In the rest of the article, I suppose you already have an account configured for the provider.

Pivotal Cloud Foundry

Pivotal Cloud Foundry is the Cloud offering from Pivotal, based on Cloud Foundry. By registering, you have a 60-days free trial, which I happily use.

Pivotal CF requires a local executable to push apps. There’s one such executable for each major platform (Windows, Mac, Linux deb and Linux rpm). Once installed, it requires authentication with the same credentials as with your Pivotal CF account.

To push, one uses the cf push command. This commands needs at least the application name, which can be provided either on the command line cf push myapp or via a manifest.yml file. If one doesn’t provide a manifest, every file (from where the command is launched) will be pushed recursively to the cloud. However, Pivotal CF won’t be able to understand the format of the app in this case. Let’s be explicit and provide both a name and the path to the executable JAR in the manifest.yml:

---
applications:
-   name: product
    path: target/microservice-sample.jar

Notice I didn’t put the version in the JAR name. By default, Maven will generate a standard JAR will only the apps resources and through the Spring Boot plugin, a fat JAR that includes all the necessary libraries. This last JAR is the one to be pushed to Pivotal CF. This requires a tweak to the POM to removing the version name in it:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <finalName>${project.artifactId}</finalName>
  </configuration>
</plugin>

Calling cf push at this point will push the fat JAR to Pivotal CF. The output should read something like that:

Using manifest file /Volumes/Data/IdeaProjects/microservice-sample/manifest.yml
Updating app product in org frankel / space development as [email protected]
OK
Uploading product...
Uploading app files from: /Volumes/Data/IdeaProjects/microservice-sample/target/microservice-sample.jar
Uploading 871.1K, 109 files
Done uploading
OK
Stopping app product in org frankel / space development as [email protected]
OK
Starting app product in org frankel / space development as [email protected]
-----> Downloaded app package (26M)
-----> Java Buildpack Version: v3.2 | https://github.com/cloudfoundry/java-buildpack.git=3b68024
-----> Downloading Open Jdk JRE 1.8.0_60 from
       https://download.run.pivotal.io/openjdk/trusty/x86_64/openjdk-1.8.0_60.tar.gz (0.9s)
       Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.0s)
-----> Downloading Open JDK Like Memory Calculator 2.0.0_RELEASE from
       https://download.run.pivotal.io/memory-calculator/trusty/x86_64/memory-calculator-2.0.0_RELEASE.tar.gz (0.0s)
       Memory Settings: -XX:MetaspaceSize=104857K -Xmx768M -XX:MaxMetaspaceSize=104857K -Xss1M -Xms768M
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from
       https://download.run.pivotal.io/auto-reconfiguration/auto-reconfiguration-1.10.0_RELEASE.jar (0.0s)
-----> Uploading droplet (71M)
0 of 1 instances running, 1 starting
1 of 1 instances running
App started
OK
App product was started using this command
 `CALCULATED_MEMORY=$($PWD/.java-buildpack/open_jdk_jre/bin/java-buildpack-memory-calculator-2.0.0_RELEASE
 -memorySizes=metaspace:64m.. -memoryWeights=heap:75,metaspace:10,native:10,stack:5
 -memoryInitials=heap:100%,metaspace:100%
 -totMemory=$MEMORY_LIMIT) && SERVER_PORT=$PORT $PWD/.java-buildpack/open_jdk_jre/bin/java
 -cp $PWD/.:$PWD/.java-buildpack/spring_auto_reconfiguration/spring_auto_reconfiguration-1.10.0_RELEASE.jar
 -Djava.io.tmpdir=$TMPDIR -XX:OnOutOfMemoryError=$PWD/.java-buildpack/open_jdk_jre/bin/killjava.sh $CALCULATED_MEMORY
 org.springframework.boot.loader.JarLauncher`
Showing health and status for app product in org frankel / space development as [email protected]
OK
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: product.cfapps.io
last uploaded: Sun Sep 27 09:05:49 UTC 2015
stack: cflinuxfs2
buildpack: java-buildpack=v3.2-https://github.com/cloudfoundry/java-buildpack.git=3b68024 java-main
             open-jdk-like-jre=1.8.0_60 open-jdk-like-memory-calculator=2.0.0_RELEASE
             spring-auto-reconfiguration=1.10.0_RELEASE
     state     since                    cpu    memory         disk           details
=0   running   2015-09-27 11:06:35 AM   0.0%   635.5M of 1G   150.4M of 1G

With the modified configuration, Pivotal CF is able to detect it’s a Java Spring Boot application and deploy it. It’s now accessible at https://product.cfapps.io/products!

However, this application doesn’t reflect a real-world one for it still uses the h2 embedded database. Let’s decouple the database from the application but only when in the cloud, as h2 should still be used locally.

The first step is to create a new database service in Pivotal CF. Nothing fancy here, as JPA is used, we will use a standard SQL database. The ClearDB MySQL service is available in the marketplace and the SparkDB is available for free. Let’s create a new instance for our app and give it a relevant name (mysql-service in my case). It can be done either in the Pivotal CF GUI or via the command-line.

The second step is to bind the service to the app and it can also be achieved either way or even by declaring it in the manifest.yml.

The third step is to actually use it and thanks to Pivotal CF auto-reconfiguration feature, there’s nothing to do at this point! During deployment, the platform will introspect the app and replace the existing h2 data source with one wrapping the MySQL database. This can be asserted by checking the actuator (provided it has been added as a dependency).

This is it for pushing the Spring Boot app to Pivotal CF. Next week, let’s deploy to Heroku to check if there are any differences.

The complete source code for this post can be found on Github.
Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with focused interests like Rich Internet Applications, Testing, CI/CD and DevOps. Currently working for Hazelcast. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More