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 xxx@frankel.ch... 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 xxx@frankel.ch... OK Starting app product in org frankel / space development as xxx@frankel.ch... -----> 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 xxx@frankel.ch... 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.