I wanted to know how easy it would be to get Spring-Boot auto-reconfiguration to work in OpenShift. It did not really work for me in Cloud Foundry without some massaging ( auto re-config blog ).

The proper way would be to extend https://github.com/spring-projects/spring-cloud/tree/master/spring-cloud-core for OpenShift Which is probably dead simple, too, but I wanted to do a quick 30 minute hack which become about a 90 minutes dirty hack.

In simple terms, the cartridge always sets -Dspring.profiles.active=cloud (unless this is overwritten by the app developer). And when it finds a ‘OPENSHIFT_MYSQL_DB_URL’ environment variable (which means the user added that service (cartridge) to the application, then the cartridge will add a the MariaDB (MySQL) information to ‘VCAP_SERVICES’ In addition I als set ‘VCAP_APPLICATION’ to some partially correct values, as well as VCAP_APP_HOST and VCAP_APP_PORT.

Then I deployed the jar generated from the unfamous-quotes cloud-foundry-autoreconfig-tests branch and it correctly picked up the MySQL DB and SUCCESS.

It was ridiculously easy to get that working in OpenShift. If I hadn’t put in a typo in one of my first attempts it would have been even easier.

What I did not mentioned in the last blog was that the version of the “unfamous quotes” code only works on Cloud Foundry if there is a data source supplied by Cloud Foundry. Otherwise you get:

org.springframework.cloud.CloudException: No unique service matching interface javax.sql.DataSource found. Expected 1, found 0

This happens due to the this code in DataSourceConfiguration:

return connectionFactory().dataSource();    

With the current version of the spring runner cartridge the same happens: You have to add a MariaDB or it wont work.

Since this was just a quick and dirty test, I did not add any other DB services. But I also would rather check out the spring-core-cloud and create an OpenShift Cloud Connector.

I started with the code from https://github.com/spring-guides/gs-accessing-data-jpa.git (complete). I then added a simple HTML/JS UI on top of the Restful API and added validation.

The way Spring Boot works in this set-up is that it automatically creates an in-memory H2 DB and auto-wires everything together. There is basically no code and it works fine and is simple enough. All in an executable Jar with an embedded Tomcat (~29M).

I uploaded that example to different Cloud PaaS providers as well as private PaaS running in a VM and it
either required no or very little effort to run it (except for one where it failed completely … see previous posts).

What surprised me was that Cloud Foundry does not seem to support auto-reconfig for a jar packaged Spring Boot application. When I added a MySQL service and happily expected it to magically work and instead Cloud Foundry continued to start with the H2 DB (relevant git commit).

I tried different set-ups, but in the end I had to add an additional Spring cloud configuration file:

public class DataSourceConfiguration {
    @Configuration()
    public static class CloudConfiguration extends AbstractCloudConfig {
        @Bean(destroyMethod = "close")
        public javax.sql.DataSource dataSource() {
            return connectionFactory().dataSource();
        }
    }
}

And it immediately picked up the MySQL DB Did not create tables, though for that I also had to set spring.jpa.hibernate.ddl-auto=update in the application.property file.

The problem with that approach is that it won’t work locally:

Caused by: org.springframework.cloud.CloudException: No suitable cloud connector found

My thought was that it might just work with using the cloud profile so I changed it

public class DataSourceConfiguration {
    @Configuration()
    @Profile({ "cloud" })
    public static class CloudConfiguration extends AbstractCloudConfig {
        @Bean(destroyMethod = "close")
        public javax.sql.DataSource dataSource() {
            return connectionFactory().dataSource();
        }
    }
}

But that profile is not set by Cloud Foundry. One option could be to set the AbstractCloudConfig profile as default and set a different (e.g. local) profile for local development (see DataSourceConfiguration commit)

This works for this project, but might not for others.

Another option could be to set the cloud profile only when deploying to Cloud Foundry via e.g. JAVA_OPTS (see older posts). Either way can be a awkward for anyone not knowing the chosen path.

I prefer the second option because it means that local development works as expected and the same code behaves exactly the same way in Cloud Foundry (ie using H2 instead of MySQL. (see DataSourceConfiguration commit for cloud profile)

And with a specific manifest.yml file this can be overwritten for Cloud Foundry (though I don’t like having this file as part of the code) so that the active Spring Profile is “cloud”. With this set-up the code uses H2 locally and will use the DB service provided by Cloud Foundry – in my case MySQL – when deployed to Cloud Foundry.

Similar to my Cloud Foundry environment notes I was interested what Stackato puts on top of the Cloud Foundry framework. This was running in a local VM that I downloaded from their site.

Deploying the app

Still using the same test code

After spending quite some time on trying to set the JAVA_OPTS, I instead changed the source code to use the environment variable instead of server.port and server.address and then re-pushed

mkdir build
cd build
unzip ../target/simple-executable-jar-web-server-0.0.1.jar
cd ..
stackato push --path /xdata/local/dev/markus/git/simple-executable-jar-web-server/build

The app worked after my code changes and the test server was up and running, but I could not log into the web console, anymore, thought I had the password wrong, but then used

stackato passwd

and it accepted my old password. Besides Firefox remembered the same password.

A server restart helped. Since I usually only pause my VMs it might have gotten confused.,

Runtime Environment and Properties

Environment

'HOME' = '/home/stackato/app'
'JAVA_OPTS' = '-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST'
'LANG' = 'en_US.UTF-8'
'LANGUAGE' = 'en_US.UTF-8'
'LC_ALL' = 'en_US.UTF-8'
'LOGNAME' = 'stackato'
'MAIL' = '/var/mail/stackato'
'MEMORY_LIMIT' = '256m'
'NLSPATH' = '/usr/dt/lib/nls/msg/%L/%N.cat'
'OLDPWD' = '/home/stackato/app'
'PACKAGES_COMMON' = 'git'
'PATH' = '/opt/ActivePython-2.7/bin:/opt/ActivePython-3.3/bin:/opt/ActivePerl-5.16/bin:/opt/rubies/current/bin:/opt/node-v0.10/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
'PORT' = '58761'
'PWD' = '/home/stackato/app'
'SHELL' = '/bin/bash'
'SHLVL' = '2'
'SSH_CLIENT' = '172.17.42.1 51755 22'
'SSH_CONNECTION' = '172.17.42.1 51755 172.17.0.86 22'
'STACKATO_APP_ENV' = 'JAVA_OPTS'
'STACKATO_APP_NAME' = 'simple-executable-jar-web-server'
'STACKATO_APP_NAME_UPCASE' = 'SIMPLE_EXECUTABLE_JAR_WEB_SERVER'
'STACKATO_APP_ROOT' = '/home/stackato'
'STACKATO_DOCKER' = 'True'
'STACKATO_LOG_FILES' = 'stdout=/home/stackato/logs/stdout.log:stderr=/home/stackato/logs/stderr.log'
'STACKATO_SERVICES' = '{}'
'TMPDIR' = '/home/stackato/tmp'
'USER' = 'stackato'
'VCAP_APPLICATION' = '{"instance_id":"e20054cb47ed479c843142b480e12f52","instance_index":0,"host":"0.0.0.0","port":58761,"started_at":"2014-06-02 06:33:19 -0700","started_at_timestamp":1401715999,"start":"2014-06-02 06:33:19 -0700","state_timestamp":1401715999,"limits":{"mem":256,"disk":2048,"fds":16384,"allow_sudo":false},"application_version":"8c5b4b0a-5e50-4d69-bf92-f4fe7c5ef0ec","application_name":"simple-executable-jar-web-server","application_uris":["simple-executable-jar-web-server.stackato-cr6q.local"],"sso_enabled":false,"version":"8c5b4b0a-5e50-4d69-bf92-f4fe7c5ef0ec","name":"simple-executable-jar-web-server","uris":["simple-executable-jar-web-server.stackato-cr6q.local"],"users":null}'
'VCAP_APP_HOST' = '0.0.0.0'
'VCAP_APP_PORT' = '58761'
'VCAP_SERVICES' = '{}'
'XFILESEARCHPATH' = '/usr/dt/app-defaults/%L/Dt'
'_' = '/home/stackato/app/.java-buildpack/open_jdk/bin/java'

System Properties

'awt.toolkit' = 'sun.awt.X11.XToolkit'
'file.encoding' = 'UTF-8'
'file.encoding.pkg' = 'sun.io'
'file.separator' = '/'
'java.awt.graphicsenv' = 'sun.awt.X11GraphicsEnvironment'
'java.awt.printerjob' = 'sun.print.PSPrinterJob'
'java.class.path' = '/home/stackato/app/.'
'java.class.version' = '51.0'
'java.endorsed.dirs' = '/home/stackato/app/.java-buildpack/open_jdk/lib/endorsed'
'java.ext.dirs' = '/home/stackato/app/.java-buildpack/open_jdk/lib/ext:/usr/java/packages/lib/ext'
'java.home' = '/home/stackato/app/.java-buildpack/open_jdk'
'java.io.tmpdir' = '/home/stackato/tmp'
'java.library.path' = '/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib'
'java.runtime.name' = 'OpenJDK Runtime Environment'
'java.runtime.version' = '1.7.0_60-b19'
'java.specification.name' = 'Java Platform API Specification'
'java.specification.vendor' = 'Oracle Corporation'
'java.specification.version' = '1.7'
'java.vendor' = 'Oracle Corporation'
'java.vendor.url' = 'http://java.oracle.com/'
'java.vendor.url.bug' = 'http://bugreport.sun.com/bugreport/'
'java.version' = '1.7.0_60'
'java.vm.info' = 'mixed mode'
'java.vm.name' = 'OpenJDK 64-Bit Server VM'
'java.vm.specification.name' = 'Java Virtual Machine Specification'
'java.vm.specification.vendor' = 'Oracle Corporation'
'java.vm.specification.version' = '1.7'
'java.vm.vendor' = 'Oracle Corporation'
'java.vm.version' = '24.80-b07'
'line.separator' = '    '
'os.arch' = 'amd64'
'os.name' = 'Linux'
'os.version' = '3.8.0-30-generic'
'path.separator' = ':'
'sun.arch.data.model' = '64'
'sun.boot.class.path' = '/home/stackato/app/.java-buildpack/open_jdk/lib/resources.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/rt.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/sunrsasign.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/jsse.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/jce.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/charsets.jar:/home/stackato/app/.java-buildpack/open_jdk/lib/jfr.jar:/home/stackato/app/.java-buildpack/open_jdk/classes'
'sun.boot.library.path' = '/home/stackato/app/.java-buildpack/open_jdk/lib/amd64'
'sun.cpu.endian' = 'little'
'sun.cpu.isalist' = ''
'sun.io.unicode.encoding' = 'UnicodeLittle'
'sun.java.command' = 'at.mnm.util.SimpleTestWebServer'
'sun.java.launcher' = 'SUN_STANDARD'
'sun.jnu.encoding' = 'UTF-8'
'sun.management.compiler' = 'HotSpot 64-Bit Tiered Compilers'
'sun.os.patch.level' = 'unknown'
'user.country' = 'US'
'user.dir' = '/home/stackato/app'
'user.home' = '/home/stackato'
'user.language' = 'en'
'user.name' = 'stackato'

Adding services

Wanted to add the service via the web UI but did not immediately see how.

stackato create-service mysql testdb simple-executable-jar-web-server

Afterwards the following new environment properties were added :

> 'DATABASE_URL' = 'mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777'
> 'JDBC_MYSQL_URL' = 'jdbc:mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777'
> 'MYSQL_URL' = 'mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777'

And these changed : < ‘STACKATO_SERVICES’ = ‘{}’ —

‘STACKATO_SERVICES’ = ‘{“testdb”:{“name”:”d415c91f5251b450d9a3c20c45b5d7777″, “hostname”:”172.16.127.133″,”host”:”172.16.127.133″,”port”:3306, “user”:”ucLE9lXtowAqf”,”username”:”ucLE9lXtowAqf”,”password”:”pYSRyL7jO1vgi”, “uri”:”mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777″, “jdbcUrl”:”jdbc:mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777″}}’

< 'VCAP_SERVICES' = '{}'
---
> 'VCAP_SERVICES' = '{"mysql":[{"name":"testdb","label":"mysql-5.5","tags":[],
    "plan":"free","credentials":{"name":"d415c91f5251b450d9a3c20c45b5d7777",
    "hostname":"172.16.127.133","host":"172.16.127.133","port":3306,
    "user":"ucLE9lXtowAqf","username":"ucLE9lXtowAqf","password":"pYSRyL7jO1vgi",
    "uri":"mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777",
    "jdbcUrl":"jdbc:mysql://ucLE9lXtowAqf:pYSRyL7jO1vgi@172.16.127.133:3306/d415c91f5251b450d9a3c20c45b5d7777"}}]}'

VCAP_APPLICATION seemed to change like for CloudFoundry – but unrelated to to service.

and this system proeprty changed, simialr to Cloud Foundry:

< 'java.class.path' = '/home/stackato/app/.'
---
> 'java.class.path' = '/home/stackato/app/.:/home/stackato/app/.java-buildpack/maria_db_jdbc/maria_db_jdbc-1.1.7.jar'

Appendix : How to Not Set Environment

Not sure how this should have worked, but it didn’t for me…

I wanted to set Java System Properties to pass in the server.address and server.port. The same worked for Cloud Foundry

Tried to figure out the right amount of escaping … this is what we want to see: ‘JAVA_OPTS’ = ‘-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST’

stackato set-env simple-executable-jar-web-server JAVA_OPTS "-Dserver.port=\\\$VCAP_APP_PORT -Dserver.address=\\\$VCAP_APP_HOST"
Unknown option -Dserver.port

stackato set-env simple-executable-jar-web-server JAVA_OPTS '-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST'
Unknown option -Dserver.port


stackato set-env simple-executable-jar-web-server JAVA_OPTS '\-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST'
Adding Environment Variable [JAVA_OPTS=\-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '\-Dserver.port=$VCAP_APP_PORT \-Dserver.address=$VCAP_APP_HOST'
...




stackato set-env simple-executable-jar-web-server JAVA_OPTS '\"-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST\"'
Adding Environment Variable [JAVA_OPTS=\"-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST\"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '\-Dserver.port=$VCAP_APP_PORT'
...


stackato set-env simple-executable-jar-web-server JAVA_OPTS "\"-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST\""
Adding Environment Variable [JAVA_OPTS="-Dserver.port=$VCAP_APP_PORT \-Dserver.address=$VCAP_APP_HOST"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '"-Dserver.port=45238 \-Dserver.address=0.0.0.0"'
...

stackato env-add simple-executable-jar-web-server JAVA_OPTS "\"-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST\""
Adding Environment Variable [JAVA_OPTS="-Dserver.port=$VCAP_APP_PORT \-Dserver.address=$VCAP_APP_HOST"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '"-Dserver.port=43998 \-Dserver.address=0.0.0.0"'
...


stackato set-env simple-executable-jar-web-server JAVA_OPTS "\-Dserver.port=\\\$VCAP_APP_PORT \-Dserver.address=\\\$VCAP_APP_HOST"
Adding Environment Variable [JAVA_OPTS=\-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '\-Dserver.port=$VCAP_APP_PORT \-Dserver.address=$VCAP_APP_HOST'
...


stackato env-add simple-executable-jar-web-server JAVA_OPTS "\"-Dserver.port=\$VCAP_APP_PORT -Dserver.address=\$VCAP_APP_HOST\""
Adding Environment Variable [JAVA_OPTS="-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '"-Dserver.port=48420 -Dserver.address=0.0.0.0"'
...

stackato env-add simple-executable-jar-web-server JAVA_OPTS "\"-Dserver.port=\\\$VCAP_APP_PORT -Dserver.address=\\\$VCAP_APP_HOST\""
Adding Environment Variable [JAVA_OPTS="-Dserver.port=\$VCAP_APP_PORT -Dserver.address=\$VCAP_APP_HOST"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '"-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST"'
...


stackato env-add simple-executable-jar-web-server JAVA_OPTS "\-Dserver.port=\\\$VCAP_APP_PORT \-Dserver.address=\\\$VCAP_APP_HOST"
Adding Environment Variable [JAVA_OPTS=\-Dserver.port=\$VCAP_APP_PORT \-Dserver.address=\$VCAP_APP_HOST] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '\-Dserver.port=$VCAP_APP_PORT \-Dserver.address=$VCAP_APP_HOST'
...

stackato env-add simple-executable-jar-web-server JAVA_OPTS '"-"Dserver.port=\$VCAP_APP_PORT "-"Dserver.address=\$VCAP_APP_HOST"'
Adding Environment Variable [JAVA_OPTS="-"Dserver.port=\$VCAP_APP_PORT "-"Dserver.address=\$VCAP_APP_HOST"] ... 
...
app[stdout.0]:    'JAVA_OPTS' = '"-"Dserver.port=$VCAP_APP_PORT "-"Dserver.address=$VCAP_APP_HOST"'
...

giving up. I use the way it works descibed at http://community.activestate.com/node/9487 (or I could use cf).

vi build/stackato.yml

app-dir: /xdata/local/dev/markus/git/simple-executable-jar-web-server/build
disk: 2048
memory: 256
name: simple-executable-jar-web-server
env:
JAVA_OPTS: "-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST"


stackato push --path /xdata/local/dev/markus/git/simple-executable-jar-web-server/build
...
app[stdout.0]:    'JAVA_OPTS' = '"-"Dserver.port=$VCAP_APP_PORT "-"Dserver.address=$VCAP_APP_HOST"'
...


stackato env-del simple-executable-jar-web-server JAVA_OPTS
Deleting Environment Variable [JAVA_OPTS] ... 



stackato push --path /xdata/local/dev/markus/git/simple-executable-jar-web-server/build
Using manifest file "build/stackato.yml"
...
Enter JAVA_OPTS [-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST]: 
  Adding Environment Variable [JAVA_OPTS=-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST]
...

but no JAVA_OPTS and no system properties

stackato env-del simple-executable-jar-web-server JAVA_OPTS


cf login  --skip-ssl-validation -a https://api.stackato-cr6q.local
API endpoint: https://api.stackato-cr6q.local
...

cf set-env simple-executable-jar-web-server JAVA_OPTS "-Dserver.port=\\\$VCAP_APP_PORT -Dserver.address=\\\$VCAP_APP_HOST"
Setting env variable 'JAVA_OPTS' to '-Dserver.port=\$VCAP_APP_PORT -Dserver.address=\$VCAP_APP_HOST' for app simple-executable-jar-web-server in org mnm.at / space demos as admin...
OK
TIP: Use 'cf push' to ensure your env variable changes take effect

rm build/stackato.yml 
stackato push --path /xdata/local/dev/markus/git/simple-executable-jar-web-server/build

even though this time the JAVA_OPTS variable looks right:

app[stdout.0]:    'JAVA_OPTS' = '-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST'

there is not server.port system property. so it seems that the build back is different (though it is the java build pack)

I want to see what mechanism is used to signal available services to an application running in Cloud Foundry.

I checked by running my non-spring test server simple-executable-jar-web-server. The server is tiny and quick to deploy.

first deploy

To run this in an Cloud Foundry environment I had to figure out how to pass the server address and port.

cf push simple-executable-jar-web-server -p target/simple-executable-jar-web-server-0.0.1.jar

The previous command will fail. I did not check if there is some other way to register an application or if it is even required before set-env)

The next line sets JAVA_OPT which in turn will set the relevant system properties on the Java command line:

cf set-env simple-executable-jar-web-server JAVA_OPTS "-Dserver.port=\\\$VCAP_APP_PORT -Dserver.address=\\\$VCAP_APP_HOST"

This time it will work:

cf push simple-executable-jar-web-server -p target/simple-executable-jar-web-server-0.0.1.jar

I believe the port will change every time you push.

The value of the VCAP_APPLICATION environment variable changes after every push as well.

Specifically application_version, version, instance_id e.g space-id and application_id stay the same

< 'VCAP_APPLICATION' = '{"limits":{"mem":1024,"disk":1024,"fds":16384},
    "application_version":"12345678-1234-1234-1234-123456789012",
    "application_name":"simple-executable-jar-web-server",
    "application_uris":["simple-executable-jar-web-server.cfapps.io"],
    "version":"12345678-1234-1234-1234-123456789012","name":"simple-executable-jar-web-server",
    "space_name":"development","space_id":"spaceid12345678901234567890123456789",
    "uris":["simple-executable-jar-web-server.cfapps.io"],"users":null,
    "application_id":"appid1234567890123456789012345678901",
    "instance_id":"instanceid1234567890123456789012","instance_index":0,"host":"0.0.0.0","port":62466,
    "started_at":"2014-06-15 00:33:09 +0000","started_at_timestamp":1402792389,
    "start":"2014-06-15 00:33:09 +0000","state_timestamp":1402792389}'
---
> 'VCAP_APPLICATION' = '{"limits":{"mem":1024,"disk":1024,"fds":16384},
    "application_version":"newappli-cati-onve-rsio-n12345678901",
    "application_name":"simple-executable-jar-web-server",
    "application_uris":["simple-executable-jar-web-server.cfapps.io"],
    "version":"newappli-cati-onve-rsio-n12345678901","name":"simple-executable-jar-web-server",
    "space_name":"development","space_id":"spaceid12345678901234567890123456789",
    "uris":["simple-executable-jar-web-server.cfapps.io"],"users":null,
    "application_id":"appid1234567890123456789012345678901",
    "instance_id":"newinstanceid1234567890123456789","instance_index":0,"host":"0.0.0.0","port":62187,
    "started_at":"2014-06-15 00:44:08 +0000","started_at_timestamp":1402793048,
    "start":"2014-06-15 00:44:08 +0000","state_timestamp":1402793048}'

Pivotal’s Cloud Foundry seems to have some problem with fonts. But the UI is made in a way that you don’t know what the icons mean, since there is is alternate text and it is not obvious in the context of the UI. e.g. one of the two icons in the circle is stop and the other one restart (the circle is part of the UI, btw).

screenshot-missing-icons-cloudfoundry

Environment Variables:

'HOME' = '/home/vcap/app'
'JAVA_OPTS' = '-Dserver.port=$VCAP_APP_PORT -Dserver.address=$VCAP_APP_HOST'
'MEMORY_LIMIT' = '1024m'
'NLSPATH' = '/usr/dt/lib/nls/msg/%L/%N.cat'
'OLDPWD' = '/home/vcap'
'PATH' = '/bin:/usr/bin'
'PORT' = '62466'
'PWD' = '/home/vcap/app'
'SHLVL' = '1'
'TMPDIR' = '/home/vcap/tmp'
'USER' = 'vcap'
'VCAP_APPLICATION' = '{"limits":{"mem":1024,"disk":1024,"fds":16384},"application_version":"12345678-1234-1234-1234-123456789012","application_name":"simple-executable-jar-web-server","application_uris":["simple-executable-jar-web-server.cfapps.io"],"version":"12345678-1234-1234-1234-123456789012","name":"simple-executable-jar-web-server","space_name":"development","space_id":"spaceid12345678901234567890123456789","uris":["simple-executable-jar-web-server.cfapps.io"],"users":null,"application_id":"appid1234567890123456789012345678901","instance_id":"instanceid1234567890123456789012","instance_index":0,"host":"0.0.0.0","port":62466,"started_at":"2014-06-15 00:33:09 +0000","started_at_timestamp":1402792389,"start":"2014-06-15 00:33:09 +0000","state_timestamp":1402792389}'
'VCAP_APP_HOST' = '0.0.0.0'
'VCAP_APP_PORT' = '62466'
'VCAP_SERVICES' = '{}'
'XFILESEARCHPATH' = '/usr/dt/app-defaults/%L/Dt'
'_' = '/home/vcap/app/.java-buildpack/open_jdk_jre/bin/java'

System Properties

'awt.toolkit' = 'sun.awt.X11.XToolkit'
'file.encoding' = 'ANSI_X3.4-1968'
'file.encoding.pkg' = 'sun.io'
'file.separator' = '/'
'java.awt.graphicsenv' = 'sun.awt.X11GraphicsEnvironment'
'java.awt.printerjob' = 'sun.print.PSPrinterJob'
'java.class.path' = '/home/vcap/app/.'
'java.class.version' = '51.0'
'java.endorsed.dirs' = '/home/vcap/app/.java-buildpack/open_jdk_jre/lib/endorsed'
'java.ext.dirs' = '/home/vcap/app/.java-buildpack/open_jdk_jre/lib/ext:/usr/java/packages/lib/ext'
'java.home' = '/home/vcap/app/.java-buildpack/open_jdk_jre'
'java.io.tmpdir' = '/home/vcap/tmp'
'java.library.path' = '/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib'
'java.runtime.name' = 'OpenJDK Runtime Environment'
'java.runtime.version' = '1.7.0_60-b19'
'java.specification.name' = 'Java Platform API Specification'
'java.specification.vendor' = 'Oracle Corporation'
'java.specification.version' = '1.7'
'java.vendor' = 'Oracle Corporation'
'java.vendor.url' = 'http://java.oracle.com/'
'java.vendor.url.bug' = 'http://bugreport.sun.com/bugreport/'
'java.version' = '1.7.0_60'
'java.vm.info' = 'mixed mode'
'java.vm.name' = 'OpenJDK 64-Bit Server VM'
'java.vm.specification.name' = 'Java Virtual Machine Specification'
'java.vm.specification.vendor' = 'Oracle Corporation'
'java.vm.specification.version' = '1.7'
'java.vm.vendor' = 'Oracle Corporation'
'java.vm.version' = '24.80-b07'
'line.separator' = '
'
'os.arch' = 'amd64'
'os.name' = 'Linux'
'os.version' = '3.0.0-32-virtual'
'path.separator' = ':'
'server.address' = '0.0.0.0'
'server.port' = '62466'
'sun.arch.data.model' = '64'
'sun.boot.class.path' = '/home/vcap/app/.java-buildpack/open_jdk_jre/lib/resources.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/rt.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/sunrsasign.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/jsse.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/jce.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/charsets.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/lib/jfr.jar:/home/vcap/app/.java-buildpack/open_jdk_jre/classes'
'sun.boot.library.path' = '/home/vcap/app/.java-buildpack/open_jdk_jre/lib/amd64'
'sun.cpu.endian' = 'little'
'sun.cpu.isalist' = ''
'sun.io.unicode.encoding' = 'UnicodeLittle'
'sun.java.command' = 'at.mnm.util.SimpleTestWebServer'
'sun.java.launcher' = 'SUN_STANDARD'
'sun.jnu.encoding' = 'ANSI_X3.4-1968'
'sun.management.compiler' = 'HotSpot 64-Bit Tiered Compilers'
'sun.os.patch.level' = 'unknown'
'user.country' = 'US'
'user.dir' = '/home/vcap/app'
'user.home' = '/home/vcap'
'user.language' = 'en'
'user.name' = 'vcap'
'user.timezone' = 'Etc/UTC'

Services

MySQL – without any other services

I added the free-tier MySQL (I called the instance ‘SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL’) service from the market place.

Couldn’t restart my app, it sometimes stopped but then did not start, most of the time restarts did nothing.

In the end I pushed the app again, which is what the WEB UI suggests.

Binding MySQL changed the following environment and system properties :

A new environment variables was added by Cloud Foundry:

'DATABASE_URL' = 'mysql2://username123456:12345678@us-cdbr-east-06.cleardb.net:3306/ad_123456789012345?reconnect=true'

The following environment variables where changed by Cloud Foundry ( apart from ports and the VCAP_APPLICATION ones )

< 'VCAP_SERVICES' = '{}'
---
> 'VCAP_SERVICES' = '{"cleardb":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL","label":"cleardb","tags":
    ["relational","Data Store","mysql"],"plan":"spark","credentials":{
    "jdbcUrl":"jdbc:mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012",
    "uri":"mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012?reconnect=true",
    "name":"dbname123456789012","hostname":"us-cdbr-east-06.cleardb.net","port":"3306",
    "username":"username123456","password":"passwd12"}}]}'  

Changes to system properties:

<    'java.class.path' = '/home/vcap/app/.'
---
>    'java.class.path' = '/home/vcap/app/.:/home/vcap/app/.java-buildpack/maria_db_jdbc/maria_db_jdbc-1.1.7.jar'

(As well as port changes.)

PostgreSQL in addition to MySQL

Added new free tier PostgreSQL service SOME-INSTANCE-NAME-I-CHOSE-FOR-PGSQL and after binding it to my test app pushed the app up again

Changes to environment variables:

< 'VCAP_SERVICES' = '{"cleardb":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL","label":"cleardb","tags":
    ["relational","Data Store","mysql"],"plan":"spark","credentials":{
    "jdbcUrl":"jdbc:mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012",
    "uri":"mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012?reconnect=true",
    "name":"dbname123456789012","hostname":"us-cdbr-east-06.cleardb.net","port":"3306",
    "username":"username123456","password":"passwd12"}}]}'
---
> 'VCAP_SERVICES' = '{"cleardb":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL","label":"cleardb","tags":
    ["relational","Data Store","mysql"],"plan":"spark","credentials":{
    "jdbcUrl":"jdbc:mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012",
    "uri":"mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012?reconnect=true",
    "name":"dbname123456789012","hostname":"us-cdbr-east-06.cleardb.net","port":"3306",
    "username":"username123456","password":"passwd12"}}],
    "elephantsql":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-PGSQL","label":"elephantsql",
    "tags":["New Product","relational","Data Store","postgresql"],"plan":"turtle","credentials":{
    "uri":"postgres://user1234:encodedpassword12345678901234567@babar.elephantsql.com:5432/user1234",
    "max_conns":"5"}}]}'

Changes to system variables:

< 'java.class.path' = '/home/vcap/app/.:/home/vcap/app/.java-buildpack/maria_db_jdbc/maria_db_jdbc-1.1.7.jar'
---
> 'java.class.path' = '/home/vcap/app/.:/home/vcap/app/.java-buildpack/maria_db_jdbc/maria_db_jdbc-1.1.7.jar:/home/vcap/app/.java-buildpack/postgresql_jdbc/postgresql_jdbc-9.3.1101.jar'

notable is that ‘DATABASE_URL’ still did not change, I assume it might be the first relational DB (or is only used for MySQL)

Added Redis in addition to MySQL and PostgreSQL

Added the free tier Redis service (‘SOME-INSTANCE-NAME-I-CHOSE-FOR-REDIS’)

Changes to environment variables

< 'VCAP_SERVICES' = '{"cleardb":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL","label":"cleardb","tags":
    ["relational","Data Store","mysql"],"plan":"spark","credentials":{
    "jdbcUrl":"jdbc:mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012",
    "uri":"mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012?reconnect=true",
    "name":"dbname123456789012","hostname":"us-cdbr-east-06.cleardb.net","port":"3306",
    "username":"username123456","password":"passwd12"}}],
    "elephantsql":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-PGSQL","label":"elephantsql",
    "tags":["New Product","relational","Data Store","postgresql"],"plan":"turtle","credentials":{
    "uri":"postgres://user1234:encodedpassword12345678901234567@babar.elephantsql.com:5432/user1234",
    "max_conns":"5"}}]}'
---
> 'VCAP_SERVICES' = '{"rediscloud":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-REDIS","label":"rediscloud","tags":
    ["key-value","redis","Data Store"],"plan":"25mb","credentials":{
    "port":"17750","hostname":"pub-redis-17750.us-east-1-3.3.ec2.garantiadata.com","password":"redispasswd12345"}}],
    "cleardb":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-MYSQL","label":"cleardb","tags":
    ["relational","Data Store","mysql"],"plan":"spark","credentials":{
    "jdbcUrl":"jdbc:mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012",
    "uri":"mysql://username123456:passwd12@us-cdbr-east-06.cleardb.net:3306/dbname123456789012?reconnect=true",
    "name":"dbname123456789012","hostname":"us-cdbr-east-06.cleardb.net","port":"3306",
    "username":"username123456","password":"passwd12"}}], 
    "elephantsql":[{"name":"SOME-INSTANCE-NAME-I-CHOSE-FOR-PGSQL","label":"elephantsql",
    "tags":["New Product","relational","Data Store","postgresql"],"plan":"turtle","credentials":{
    "uri":"postgres://user1234:encodedpassword12345678901234567@babar.elephantsql.com:5432/user1234",
    "max_conns":"5"}}]}'

(No changes to system variables.)

General Thoughts about Cloud Foundry

The web-UI is quite slow. I mean up to 5 seconds per click slow when doing things like checking the looking at the list of apps. Even when it is not that slow it is never fast (less than 1.5 sec)

I find the UI generally a bit disappointing.

After pushing a custom spring boot app to CF, the app worked at once. No tinkering (unlike stackato).