Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

io.pivotal.cfenv:java-cfenv-parent

Package Overview
Maintainers
3
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

io.pivotal.cfenv:java-cfenv-parent

Java Library for Accessing Cloud Foundry Environment Variables

  • 2.3.0
  • Source
  • Maven

Version published
Maintainers
3
Source

= Java CFEnv image:https://build.spring.io/plugins/servlet/wittified/build-status/CFENV-BMASTER[Build Status, link=https://build.spring.io/browse/CFENV-BMASTER]

Java CFEnv is a library for easily accessing the environment variables set when deploying an application to Cloud Foundry. It is modeled after the design of the node library https://github.com/cloudfoundry-community/node-cfenv/[node-cfenv] and other -cfenv libraries in the Cloud Foundry ecosystem.

The class CfEnv is the entry point to the API for accessing Cloud Foundry environment variables. In a Spring application, you can use the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-bean-references[Spring Expression Language] to invoke methods on bean of type CfEnv to set properties. CFEnv's Boot support sets https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties[common application properties] so that Java objects such as the DataSource or the RabbitConnectionFactory are created using Spring Boot autoconfiguration.

The https://spring.io/blog/2019/02/15/introducing-java-cfenv-a-new-library-for-accessing-cloud-foundry-services[1.0 M1 blog] provides some additional background information.

== Compatibility === https://github.com/pivotal-cf/java-cfenv/tree/main[3.x]

=== https://github.com/pivotal-cf/java-cfenv/tree/2.5.x[2.x]

== Dependency Info

You can access the stable release from maven central using the coordinates

[source,xml]

io.pivotal.cfenv java-cfenv-boot 3.1.3 ----

== SCS and SSO modules If you're attempting to connect a client app to a https://docs.pivotal.io/spring-cloud-services/3-1/common/client-dependencies.html[Spring Cloud Services] or https://docs.pivotal.io/p-identity/1-11/integrating-sso.html[Single Sign-On] service instance, you should follow their respective docs.

== Introduction The entry point 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. For example, here is the value of VCAP_SERVICES for an application bound to the mysql and redis services.

[source,json]

{ "p-mysql": [ { "credentials": { "hostname": "10.0.4.35", "port": 3306, "name": "cf_2e23d10a_8738_8c3c_66cf_13e44422698c", "username": "8McHri7aKbuTEGCR", "password": "J2BNJYkeXAH9idkG", "uri": "mysql://8McHri7aKbuTEGCR:J2BNJYkeXAH9idkG@10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?reconnect=true", "jdbcUrl": "jdbc:mysql://10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?user=8McHri7aKbuTEGCR&password=J2BNJYkeXAH9idkG" }, "syslog_drain_url": null, "volume_mounts": [], "label": "p-mysql", "provider": null, "plan": "100mb", "name": "mysql", "tags": [ "mysql", "relational" ] } ], "p-redis": [ { "credentials": { "host": "10.0.4.30", "password": "291452d8-d4a1-3bec-90d9-g50503138248", "port": 45470 }, "syslog_drain_url": null, "volume_mounts": [], "label": "p-redis", "provider": null, "plan": "shared-vm", "name": "redis", "tags": [ "pivotal", "redis" ] } ], "nfs": [ { "binding_name": null, "credentials": {}, "instance_name": "nfs1", "label": "nfs", "name": "nfs1", "plan": "Existing", "provider": null, "syslog_drain_url": null, "tags": [ "nfs" ], "volume_mounts": [ { "container_dir": "/var/vcap/data/78525ee7-196c-4ed4-8ac6-857d15334631", "device_type": "shared", "mode": "rw" } ] } ] }

The keys in the JSON are not always identical across services, for example in the above JSON the mysql service has added the key named hostname to the credentials while the redis service has contributed the key named host. Most relational database services do not expose a key named jdbcUrl so the URL needs to be created by extracting individual fields and building up the URL string. Since this is such a common case, the CfEnv library provides support to retrieve the URL string for several databases.

To get access to a specific service's credentials, the keys tag, name, or label can be specified as a criteria for selecting one of the services in the array.

== Basic usage Using the JSON from the previous section, here are some simple API calls to extract credential information.

[source,java]

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

Multiple strings can be passed to match against more than one tag. There are additional finder methods to search by name and label and the finder method support passing a regex string for pattern matching.

The classes CfService and CfCredentials are returned from the following API calls and have methods for accessing common fields in addition to a generic get(String) map API.

[source,java]

CfEnv cfEnv = new CfEnv(); List cfService = cfEnv.findAllServices();

CfService redisService = cfEnv.findServiceByTag("redis"); List 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");

The class CfVolume contains information for a shared disk provided by Cloud Foundry volume services. You can access it using the getVolumes method on CfService as shown below.

[source,java]

CfEnv cfEnv = new CfEnv(); List cfVolumes = cfEnv.findServiceByName("nfs1").getVolumes(); String path = cfVolumes.get(0).getPath();

=== JDBC Support

There is additional support for getting the JDBC URL contained in the module spring-cfenv-jdbc. The entry point to the API 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. [source,java]

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

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

If there is more than one database bound to the application, an exception will be thrown and you should use the findJdbcServiceByName method to locate a unique database service.

[source,java]

String jdbcUrl1 = cfJdbcEnv.findJdbcServiceByName("mysqlA").getUrl(); String jdbcUrl2 = cfJdbcEnv.findJdbcServiceByName("mysqlB").getUrl();

If you are creating a user-provided-service in order to connect to a database by jdbc, provide a uri property along with username and password in the credentials block.

[source,bash]

cf cups sqlserver-ups -p '{ "uri": "sqlserver://hostname:1433;database=test_db", "username": "someuser", "password": "whatmeworry?" }'

Alternatively, you can simply provide a fully qualified jdbcUrl.

[source,bash]

cf cups sqlserver-ups -p '{ "jdbcUrl": "jdbc:sqlserver://hostname:1433;database=test_db;user=someuse;password=whatmeworry?" }'

In either case, consult your database provider's documentation on the correct format of a connection uri. This library will preserve any platform specific uri elements.

=== Use with Spring

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

[source,java]

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

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

[source]

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

Or say for cassandra, you can use the CfEnv class registered as a bean.

[source,java]

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

[source]

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

Similar for setting a custom application property to access the disk mounted by Volume Services. [source]

myapp.config.path=#{ cfEnv.findServiceByName("nfs1").getVolumes().get(0).getPath() }

=== Using Spring Boot

Please check the dedicated README for link:java-cfenv-boot/README.adoc[Spring Boot].

=== Connecting Multiple Instances of a Single Service Type

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, you will need to follow the approach layed out in the sections above (Basic Usage, JDBC Support, Use with Spring) to access the binding credentials. Then follow the same procedure that would be used to connect to your services in any other deployment environment.

=== Pushing your application to Cloud Foundry

You must disable the java buildpack's auto-reconfiguration so that you always delegate to Boot to create beans.

[source]

cf set-env JBP_CONFIG_SPRING_AUTO_RECONFIGURATION '{enabled: false}'

Since the auto-reconfiguration also set the cloud profile, you will have to do that explicitly

[source]

cf set-env SPRING_PROFILES_ACTIVE cloud

== Supporting other Services

The interface https://github.com/pivotal-cf/java-cfenv/blob/master/java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/CfEnvProcessor.java[`CfEnvProcessor`] simplifies what you need to write in most cases. The environment post processor, https://github.com/pivotal-cf/java-cfenv/blob/master/java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/CfEnvironmentPostProcessor.java[`CfEnvPostProcessor`] delegates to all CfEnvProcessors that are discovered using Spring's SpringFactoriesLoader. Here is the implementation for MongoDB

[source,java]

public class MongoCfEnvProcessor implements CfEnvProcessor {

private static String mongoScheme = "mongodb";

@Override public boolean accept(CfService service) { <1> return service.existsByTagIgnoreCase("mongodb") || service.existsByLabelStartsWith("mongolab") || service.existsByUriSchemeStartsWith(mongoScheme) || service.existsByCredentialsContainsUriField(mongoScheme); }

@Override public void process(CfCredentials cfCredentials, Map<String, Object> properties) { <2> properties.put("spring.data.mongodb.uri", cfCredentials.getUri(mongoScheme)); }

@Override public CfEnvProcessorProperties getProperties() { <3> return CfEnvProcessorProperties.builder() .propertyPrefixes("spring.data.mongodb") .serviceName("MongoDB") .build(); } }

<1> In the accept method is where you put determine how to identify your service type. The CfService class has several methods to help make this as easy as possible. <2> Copy over necessary values from the CfCredentails object to Spring Boot auto-configuration keys. <3> Create a CfEnvProcessorProperties instance so that logging which is done in CfEnvPostProcessor reflects your specific service.

Remember to add an entry in spring.factories so that your processor can be discovered.

[source]

io.pivotal.cfenv.spring.boot.CfEnvProcessor=com.example.MyCoolServiceCfEnvProcessor

=== Building

Clone the repo and type


$ ./gradlew clean build

which will run the tests as well.

FAQs

Package last updated on 05 Mar 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc