Extending Spring Cloud Connectors

Extending Spring Cloud Connectors

Cloud Foundry allows users to define their own user provided service using the cf cli. The command is of the format

cf cups [service-name] -p "comma separated list of params"

ex: cf cups oracle-db-service -p "jdbcUrl"

Once the service is defined, the user binds the service to the application and then consumes the VCAP_SERVICES environment variable to parse the JSON file to retrieve the credentials to create a connection to the service.

Sample VCAP_SERVICES looks like:

{
 "VCAP_SERVICES": {
  "user-provided": [
   {
    "credentials": {
     "jdbcUrl": "oracle://$user:$password@$hostname:$port/$name"
    },
    "label": "user-provided",
    "name": "oracle-db-service",
    "syslog_drain_url": "",
    "tags": [],
    "volume_mounts": []
   },
   {
    "credentials": {
     "hosts": "localhost:8080",
     "password": "welcome",
     "username": "user"
    },
    "label": "user-provided",
    "name": "cassandra-service",
    "syslog_drain_url": "",
    "tags": [],
    "volume_mounts": []
   }
  ]
 }
}

In the code the developer may choose to parse this JSON to retrieve the connection details or can create custom spring cloud connectors.

There are 3 ways to extend the Spring Cloud Connectors:

Cloud platform support

Out of the box, Spring Cloud Connectors offers support for the Cloud Foundry and Heroku platforms. You can extend Spring Cloud Connectors to provide support for other cloud platforms and providers.

Spring Cloud Connectors uses the CloudConnector interface to provide cloud platform support. A CloudConnector implementation for a particular cloud platform is responsible for detecting when the application is running in that cloud platform, obtaining information about the application from the cloud platform, and obtaining information about the services that are bound to the application.

Cloud service support

You can extend Spring Cloud Connectors to support additional services, including services that are specific to your own environment or application.

Spring Cloud Connectors uses two interfaces to provide cloud service support:

A ServiceInfo models the information required to connect to the service. In the case of a database service, a ServiceInfo implementation might include fields for host, port, database name, username, and password; in the case of a web service, it might include fields for URL and API key.

A ServiceInfoCreator creates ServiceInfo objects based on the service information collected by a cloud connector. A ServiceInfoCreator implementation is specific to a cloud platform.

Application framework support

The Spring Cloud Spring Service Connector creates service connectors with Spring Data data types. You can extend Spring Cloud Connectors to provide service connection objects using another framework.

Spring Cloud Connectors uses the ServiceConnectorCreator interface to provide framework support. A ServiceConnectorCreator creates service connectors using the service connection information provided by a ServiceInfo object.

Example

Lets look at creating a Kafka Service Info and connector to consume a Kafka user provided service

  • Create a KafkaServiceInfo by extending the BaseServiceInfo from the spring-cloud-connector library
package com.example.kafka;

import org.springframework.cloud.service.BaseServiceInfo;

public class KafkaServiceInfo extends BaseServiceInfo {

    public KafkaServiceInfo(String id) {
        super(id);
    }

    public KafkaServiceInfo(String id, String url, String username, String password) {
        super(id);
        this.url = url;
        this.username = username;
        this.password = password;
    }

    private String url;
    private String username;
    private String password;

    @ServiceProperty
    public String getUrl() {
        return url;
    }

    @ServiceProperty
    public String getUsername() {
        return username;
    }

    @ServiceProperty
    public String getPassword() {
        return password;
    }

    @Override
    public String toString() {
        return "KafkaServiceInfo [url=" + url + ", username=" + username + ", password=" + password + "]";
    }

}
  • Create a KafkaServiceInfoCreator by extending CloudFoundryServiceInfoCreator
package com.example.kafka;

import java.util.Map;

import org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator;
import org.springframework.cloud.cloudfoundry.Tags;

public class KafkaServiceInfoCreator extends CloudFoundryServiceInfoCreator<KafkaServiceInfo> {

    public KafkaServiceInfoCreator() {
        super(new Tags(""), "kafka");
    }

    @Override
    public KafkaServiceInfo createServiceInfo(Map<String, Object> serviceData) {
        @SuppressWarnings("unchecked")
        Map<String, Object> credentials = (Map<String, Object>) serviceData.get("credentials");

        String id = (String) serviceData.get("name");
        String servers = (String) credentials.get("servers");
        String clientId = (String) credentials.get("clientId");

        return new KafkaServiceInfo(id, servers, clientId);
    }

    @Override
    public boolean accept(Map<String, Object> serviceData) {
        String name = (String) serviceData.get("name");
        return name.startsWith("kafka"); // Kicks in only if the service name starts with kafka
    }

}

The KafkaServiceInfoCreator parses the json presented by the VCAP_SERVICES and creates the KafkaServiceInfo and its ready for use in the code.

  • To allow these classes to be discovered by spring cloud connectors, create a file org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator in src/main/resources/META-INF/services/ and add the com.example.kafka.KafkaServiceInfoCreator to it

  • To consume the kafka-service that is created using the cf clicf cups kafka-service -p 'servers,clientId'

the following code is required

  Cloud cloud = new CloudFactory().getCloud();
  KafkaServiceInfo kafkaServiceInfo = (KafkaServiceInfo) cloud.getServiceInfo("kafka-service");
  • Now the KafkaServiceInfo is ready for creating a connection to Kafka service

References

문의