1

I really want to use container managed transactions with JPA and therefor would go the easy way of having the data source creation within the server.xml and then using the @PersistenceContext within my code.

The problem I currently face - and maybe I am thinking too complicated - is the fact that I get the credentials during runtime in my Cloud Foundry environment as VCAP_SERVICES system environment variable.

This VCAP_SERVICES variable contains a big JSON with the necessary credentials. Therefor I would first have to extract the corresponding JSON within this and pass it then as property.

My initial idea was to use converters for this case returning the values out of the JSON so that they can be used. But it seems like this is not possible within a defined configuration xml file.

What I for sure want to prevent is the "injection" of something doing on my own like having a property file and copying the values from the different environments DEV, TEST, PROD in there as the Cloud Foundry environment is already doing the job for me.

So the question is: How can I get the credentials from the VCAP_SERVICES system environment variable into the server.xml configuration? Remember: I really have to parse the VCAP_SERVICES variable as this is JSON and extract the values.

<?xml version="1.0" encoding="UTF-8"?>
<server description="Config example">

    <featureManager>
        <feature>javaee-8.0</feature>
        <feature>mpMetrics-1.1</feature>
        <feature>monitor-1.0</feature>
    </featureManager>

    <!-- Postgres config-example-db definition -->
    <dataSource id="DefaultDataSource" jndiName="jdbc/config-example" jdbcDriverRef="postgresql-driver"
                type="javax.sql.ConnectionPoolDataSource" transactional="true">

        <properties serverName="config-example-db" portNumber="5432"
                    databaseName="postgres"
                    user="${config-example.db.username}"
                    password="${config-example.db.password}"/>

    </dataSource>

    <basicRegistry id="basic" realm="MicroProfileMetrics">
        <user name="admin" password="adminadmin"/>
        <user name="nonadmin" password="guest"/>
    </basicRegistry>

    <administrator-role>
        <user>admin</user>
    </administrator-role>

</server>
Inkvine
  • 129
  • 7

1 Answers1

0

For many services the liberty buildpack will auto-config the server.xml.
postgresql is one of them. See: https://github.com/cloudfoundry/ibm-websphere-liberty-buildpack/blob/master/docs/services/postgresql.md

Additionally, for many services, the buildpack will create environment variables that are then accessible by the application.

For example, binding a cloudantNoSQL service to an app results in the following credentials in VCAP_SERVICES:

{
    "binding_name": null,
    "credentials": {
     "apikey": "<apikey>",
     "host": "<host>-bluemix.cloudantnosqldb.test.appdomain.cloud",
     "iam_apikey_description": "Auto-generated for binding <host>",
     "iam_apikey_name": "Cloudant-sd",
     "iam_role_crn": "crn:v1:bluemix:public:iam::::serviceRole:Writer",
     "iam_serviceid_crn": "crn:v1:staging:public:iam-identity::<id>::serviceid:ServiceId-<serviceid>",
     "url": "https://<host>-bluemix.cloudantnosqldb.test.appdomain.cloud",
     "username": "<username>-bluemix"
    },

The buildpack will then create variables in the runtime-vars.xml:

 <variable name='cloud.services.Cloudant-sd.label' value='cloudantNoSQLDB'/>
  <variable name='cloud.services.Cloudant-sd.plan' value='Lite'/>
  <variable name='cloud.services.Cloudant-sd.name' value='Cloudant-sd'/>
  <variable name='cloud.services.Cloudant-sd.instance_name' value='Cloudant-sd'/>
  <variable name='cloud.services.Cloudant-sd.connection.apikey' value='<apikey'/>
  <variable name='cloud.services.Cloudant-sd.connection.host' value='<host>-bluemix.cloudantnosqldb.test.appdomain.cloud'/>
  <variable name='cloud.services.Cloudant-sd.connection.iam_apikey_description' value='Auto-generated for binding <host>'/>
  <variable name='cloud.services.Cloudant-sd.connection.iam_apikey_name' value='Cloudant-sd'/>
  <variable name='cloud.services.Cloudant-sd.connection.iam_role_crn' value='crn:v1:bluemix:public:iam::::serviceRole:Writer'/>
  <variable name='cloud.services.Cloudant-sd.connection.iam_serviceid_crn' value='crn:v1:staging:public:iam-identity::<id>::serviceid:ServiceId-<serviceid'/>
  <variable name='cloud.services.Cloudant-sd.connection.url' value='https://<host>-bluemix.cloudantnosqldb.test.appdomain.cloud'/>
  <variable name='cloud.services.Cloudant-sd.connection.username' value='<username>-bluemix'/>

See https://cloud.ibm.com/docs/runtimes/liberty?topic=liberty-options_for_pushing#accessing_info_of_bound_services.

  • Thanks for the info! Does the this behavior also work, when creating a JAR artifact to be pushed to CF? – Inkvine Aug 08 '19 at 18:52
  • 1
    Depends. By default the liberty buildpack will not run a JAR. If a springboot app is detected then it simply runs using java -jar . However, we recently introduced a feature to run a springboot app using Liberty's springboot support (https://cloud.ibm.com/docs/runtimes/liberty?topic=liberty-options_for_pushing#java_main) – Kevin Ortega Aug 08 '19 at 20:23
  • What would then be your preferred way of cf pushing to get the generation of variables from the build pack? – Inkvine Aug 09 '19 at 07:42
  • The build pack parses much of vcap-services into env. vars already but perhaps not completely. You might print out the environment and see how much you got. If it's incomplete, maybe open an issue over at https://github.com/OpenLiberty/open-liberty – Bruce T. Aug 09 '19 at 12:29