Configuring Service Connections

Page last updated:

The recommended path for configuring service access in your Java-based applications is to use the java-cfenv library. This library can read and parse VCAP_SERVICES and help you extract the information for use in your application.

There are a number of ways to do this and all Java applications can use the library, it is not limited to specific frameworks. To get started, you’ll first need to add a dependency in your project for the library.

Dependencies

For Maven:

<dependency>
  <groupId>io.pivotal.cfenv</groupId>
  <artifactId>java-cfenv</artifactId>
  <version>2.4.0</version>
</dependency>

For Gradle:

implementation "io.pivotal.cfenv:java-cfenv:2.4.0"

Java-Only / No Framework

The entry point for the library is the class CfEnv which parses Cloud Foundry environment variables such as VCAP_SERVICES. The information in VCAP_SERVICES is a JSON string that contains credential information to access bound services, such as a database.

This can be done by creating a CfEnv instance and using it’s findCredentialsBy* methods. There are method for finding by label, name and tag. Multiple strings can be passed to match against more than one tag and the finder method support passing a regex string for pattern matching.

For example:

CfEnv cfEnv = new CfEnv();

String redisHost = cfEnv.findCredentialsByTag("redis").getHost();
String redisPort = cfEnv.findCredentialsByTag("redis").getPort();
String redisPassword = cfEnv.findCredentialsByTag("redis").getPassword();

List<CfService> cfService = cfEnv.findAllServices();

CfService redisService = cfEnv.findServiceByTag("redis");
List<String> redisServiceTags = redisService.getTags();
String redisPlan = redisService.getPlan();
redisPlan = redisService.get("plan")

CfCredentials redisCredentials = cfEnv.findCredentialsByTag("redis");
String redisPort = redisCredentials.getPort();
Integer redisPort = redisCredentials.getMap().get("port");

cfService = cfEnv.findServiceByName("redis");
cfService = cfEnv.findServiceByLabel("p-redis");
cfService = cfEnv.findServiceByLabel(".*-redis");

JDBC Support

There is additional support for getting a JDBC URL from a service binding. This support is contained in the module java-cfenv-jdbc. To enable this, add the following additional dependency.

For Maven:

<dependency>
  <groupId>io.pivotal.cfenv</groupId>
  <artifactId>java-cfenv-jdbc</artifactId>
  <version>2.4.0</version>
</dependency>

For Gradle:

implementation "io.pivotal.cfenv:java-cfenv-jdbc:2.4.0"

The entry point for this feature is the class CfJdbcEnv which is a subclass of CfEnv and adds a few methods. The method findJdbcService will heuristically look at all services for known tags, labels and names of common database services to create the URL.

For example:

CfJdbcEnv cfJdbcEnv = new CfJdbcEnv()
CfJdbcService cfJdbcService = cfJdbcEnv.findJdbcService();

String jdbcUrl = cfJdbcService.getJdbcUrl();
String username = cfJdbcService.getUsername();
String password = cfJdbcService.getPassword();
String driverClassName = cfJdbcService.getDriverClassName();

Spring Framework

There is additional support for application developers using the Spring Framework.

Spring Expression Language

If you register the CfJdbcEnv class as a bean, then you can use the Spring Expression Language to set properties.

@Bean
public CfEnv cfEnv() {
  return new CfEnv();
}

Then in a properties file imported by Spring, refer to the CfEnv bean using the following syntax.

cassandra.contact-points=#{ cfEnv.findCredentialsByTag('cassandra').get('node_ips') }
cassandra.username=#{ cfEnv.findCredentialsByTag('cassandra').getUserName() }
cassandra.password=#{ cfEnv.findCredentialsByTag('cassandra').getPassword() }
cassandra.port=#{ cfEnv.findCredentialsByTag('cassandra').get('cqlsh_port') }

If you’re specifically targeting JDBC databases, you can register this instead.

@Bean
public CfJdbcEnv cfJdbcEnv() {
  return new CfJdbcEnv();
}

Then in a property file imported by Spring, refer to the CfJdbcEnv bean using the following syntax.

myDatasourceUrl=#{ cfJdbcEnv.findJdbcService().getUrl() }

Spring Boot

The module java-cfenv-boot provides several EnvironmentPostProcessor implementations that set well known Spring Boot properties so that Spring Boot’s auto-configuration will kick in. For example, the CfDataSourceEnvironmentPostProcessor sets the Spring Boot property spring.datasource.url.

To use these, just add a dependency on java-cfenv-boot.

For Maven:

<dependency>
  <groupId>io.pivotal.cfenv</groupId>
  <artifactId>java-cfenv-boot</artifactId>
  <version>2.4.0</version>
</dependency>

For Gradle:

implementation "io.pivotal.cfenv:java-cfenv-boot:2.4.0"

The list of supported services are:

  • Databases - DB2, MySQL, Oracle, Postgresl, SqlServer
  • RabbitMQ
  • Cassandara
  • MongoDB
  • Redis
  • CredHub
  • Hashicorp Vault

If, for any reason, you need to disable processing of a specific service instance, you can do so by setting the following flag in your application properties:

cfenv.service.{serviceName}.enabled=false

Migrating from Spring AutoReconfiguration & Spring Cloud Connectors

The java-cfenv library replaces the older Spring AutoReconfiguration and Spring Cloud Connectors libraries. The following sections will help you migrate to java-cfenv.

Change Dependencies

Remove references to any of these libraries from the application build files:

org.springframework.boot:spring-boot-starter-cloud-connectors

or

org.springframework.cloud:spring-cloud-core
org.springframework.cloud:spring-cloud-connectors-core
org.springframework.cloud:spring-cloud-cloudfoundry-connector
org.springframework.cloud:spring-cloud-spring-service-connector

Then add a reference to the java-cfenv library.

Code Changes

Remove any usages of the @ServiceScan or @CloudScan annotations from Spring Java configuration classes. These were provided by Spring Cloud Connectors.

Replace with the Spring SPeL or Spring Boot configuration options listed above.

Migration Considerations

The following additional considerations should be reviewed when migrating.

Non-Spring Boot Applications

If you have a Spring Application that is a non-Spring Boot application. You can still migrate to java-cfenv. You will need to use either the no framework options or possibly the Spring SPeL option. With SPeL, you may need to manually process the expressions though depending on where you are configuring them. Please refer to the Spring documentation for places where SPeL expressions are processed by default.

Multiple Service Instances

Spring Cloud Connectors did support connections to multiple service instances.

If you need to configure connections to multiple instances of a given service type, or do anything more than setting application properties for Spring Boot to pick up and use in auto-configuration, then you will need to follow the manual configuration approaches layed out in the sections above to access the binding credentials. Either with direct Java code or with SPeL. Then follow the same procedure that would be used to connect to your services in any other non-Cloud Foundry deployment environment.

Code Modifications

For better or worse, the Java Buildpack would inject the Spring Auto Reconfiguration module code into your application and it would overwrite your service configuration. This worked well sometimes and in other cases was a source of problems.

With java-cfenv there is no auto reconfiguration magic. You explicitly configure your services or you can utilize the Spring Boot mappers. The Spring Boot mappers are the closest option to what was previously being done here. The upshot is that when things don’t work, it’s generally more clear what happened and it’s easier to debug the problem.

Cloud Property Placeholders

The Spring Auto Reconfiguration module would expose a set of property placeholder values that one could use to access values from VCAP_SERVICES. If you are using these place holders, then you need to switch from using cloud.<property> to vcap.<property>.

Spring Boot exposes the same information, just under the vcap. prefix instead of cloud..

Spring Cloud Profile

The Spring Auto Reconfiguration module would enable a Spring Profile called cloud by default. This is often something users come to expect when deploying to Cloud Foundry. Without the Spring Auto Reconfiguration module, you do not get this behavior. Fortunately, you can enable that very easily.

Either run cf set-env <APP> SPRING_PROFILES_ACTIVE cloud or add SPRING_PROFILES_ACTIVE: cloud to the env: block in your manifest.yml file. This will supply the given list of profiles for Spring to use.

If you are setting profiles already and need to set additional profiles, you may use SPRING_PROFILES_INCLUDE instead. This will append to the existing set of profiles.

Spring Cloud Connector Extensions

If you had created any custom Spring Cloud Connector extensions, you will need to migrate those to java-cfenv. This requires two steps:

  1. Write a Spring Boot Auto Configuration library that creates connections to your service from Spring configuration properties. Doing this has the benefit of making it easy to also use in a non-cloud Spring Boot app. When this is done correctly, you should be able to use the library and set properties in application.properties (or through other means) and have a connection to your service.

  2. Write a java-cfenv extension. This is what takes values out of VCAP_SERVICES and maps them to the properties that you exposed with your Spring Boot Auto Configuration library from step number one.

Java Buildpack Warnings

There are a few warnings that the Java Buildpack will now generate to help you with the process of migratinig off of Spring Cloud Connectors and Spring Auto Reconfiguration.

Spring Auto Reconfiguration Installed

This message is generated when the buildpack installs the Spring Auto Reconfiguration JAR. This happens by default presently, so it alerts you that it is happening.

   [SpringAutoReconfiguration]      WARN  ATTENTION: The Spring Auto Reconfiguration and shaded Spring Cloud Connectors libraries are being installed. These projects have been deprecated, are no longer receiving updates and should not be used going forward.
   [SpringAutoReconfiguration]      WARN  If you are not using these libraries, set `JBP_CONFIG_SPRING_AUTO_RECONFIGURATION='{enabled: false}'` to disable their installation and clear this warning message. The buildpack will switch its default to disable by default after Aug 2022. Spring Auto Reconfiguration and its shaded Spring Cloud Connectors will be removed from the buildpack after Dec 2022.
   [SpringAutoReconfiguration]      WARN  If you are using these libraries, please migrate to java-cfenv immediately. See https://via.vmw.com/EhzD for migration instructions.

How you resolve this depends on if you are or are not depending on the Auto Reconfiguration to occur.

If your application is depending on Auto Reconfiguration behavior, then you need to make code changes in your application to use the java-cfenv library. You can see the instructions above for how to include the dependencies and how to access service information using this library.

Once you have added java-cfenv to your classpath, the Java buildpack will no longer install the Auto Reconfiguration JAR and you will no longer see this message.

If your application is not depending on Auto Reconfiguration behavior, and has already updated to java-cfenv then you should not see this message. If your application does not use Auto Reconfiguration or java-cfenv then you can either run cf set-env <APP> JBP_CONFIG_SPRING_AUTO_RECONFIGURATION '{enabled: false} or add JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '{enabled: false} to the env: block in your manifest.yml file. Alternatively, you can wait for a buildpack released after Aug 2022, when this feature will no longer be enabled by default.

Spring Cloud Connectors Present

This message is generated when the buildpack detects that the Spring Cloud Connectors library is present on the classpath.

   [SpringAutoReconfiguration]      WARN  ATTENTION: The Spring Cloud Connectors library is present in your application. This library has been in maintenance mode since July 2019 and will stop receiving all updates after Dec 2022.
   [SpringAutoReconfiguration]      WARN  Please migrate to java-cfenv immediately. See https://via.vmw.com/EhzD for migration instructions.

When this message is generated, it means that your application or a dependency it includes is including the Spring Cloud Connectors library. Since this library has been deprecated for a long time, the buildpack is simply reminding you to remove it and migrate to java-cfenv.

Once you have migrated to java-cfenv, and the Spring Cloud Connectors libraries are no longer on your classpath, this error will go away automatically. There is no way to manually surpress this message.

Create a pull request or raise an issue on the source for this page in GitHub