LATEST VERSION: 1.4 - CHANGELOG
Spring Cloud Services v1.4

Writing Client Applications

Page last updated:

Refer to the sample applications in the “greeting” repository to follow along with the code in this topic.

Add Application Dependencies for Service Registry

Important: Ensure that the ordering of the Maven BOM dependencies listed below is preserved in your application’s build file. Dependency resolution is affected in both Maven and Gradle by the order in which dependencies are declared.

To work with Spring Cloud Services service instances, your client application must include the spring-cloud-services-dependencies and spring-cloud-dependencies BOMs. Unless you are using the spring-boot-starter-parent or Spring Boot Gradle plugin, you must also specify the spring-boot-dependencies BOM as a dependency.

If using Maven, include in pom.xml:

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.pivotal.spring.cloud</groupId>
            <artifactId>spring-cloud-services-dependencies</artifactId>
            <version>1.3.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Camden.SR3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
  </dependencyManagement>

If not using the spring-boot-starter-parent, include in the <dependencyManagement> block of pom.xml:

  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.4.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- ... -->

    </dependencies>
  </dependencyManagement>

If using Gradle, you will also need to use the Gradle dependency management plugin.

Include in build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("io.spring.gradle:dependency-management-plugin:0.6.1.RELEASE")
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
    }
}

apply plugin: "java"
apply plugin: "spring-boot"
apply plugin: "io.spring.dependency-management"

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.SR3"
        mavenBom "io.pivotal.spring.cloud:spring-cloud-services-dependencies:1.3.1.RELEASE"
    }
}

repositories {
    maven {
        url "https://repo.spring.io/plugins-release"
    }
}

If not using the Spring Boot Gradle plugin, include in the dependencyManagement block of build.gradle:

dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-dependencies:1.4.1.RELEASE"
    }
}

To register your application with a Service Registry service instance or use it to consume a service that is registered with a Service Registry service instance, you must add the spring-cloud-services-starter-service-registry dependency.

If using Maven, include in pom.xml:

  <dependencies>
    <dependency>
      <groupId>io.pivotal.spring.cloud</groupId>
      <artifactId>spring-cloud-services-starter-service-registry</artifactId>
    </dependency>
  </dependencies>

If using Gradle, include in build.gradle:

dependencies {
    compile("io.pivotal.spring.cloud:spring-cloud-services-starter-service-registry")
}

Important: Because of a dependency on Spring Security, the Spring Cloud Services Starters for Service Registry will by default cause all application endpoints to be protected by HTTP Basic authentication. If you wish to disable this, please see Disable HTTP Basic Authentication below.

Add Self-Signed SSL Certificate to JVM Truststore

Spring Cloud® Services uses HTTPS for all client-to-service communication. If your Pivotal Cloud Foundry (PCF) installation is using a self-signed SSL certificate, the certificate will need to be added to the JVM truststore before your application can be registered with a Service Registry service instance or consume a service that is registered with a Service Registry service instance.

Spring Cloud Services can add the certificate for you automatically. For this to work, you must set the TRUST_CERTS environment variable on your application to the API endpoint of your Elastic Runtime instance:

$ cf set-env message-generation TRUST_CERTS api.cf.wise.com
Setting env variable 'TRUST_CERTS' to 'api.cf.wise.com' for app message-generation in org myorg / space development as user...
OK
TIP: Use 'cf restage message-generation' to ensure your env variable changes take effect
$ cf restage message-generation

Note: The CF_TARGET environment variable was formerly recommended for configuring Spring Cloud Services to add a certificate to the truststore. CF_TARGET is still supported for this purpose, but TRUST_CERTS is more flexible and is now recommended instead.

As the output from the cf set-env command suggests, restage the application after setting the environment variable.

Service Registry Peers with Self-Signed Certificates

If binding your application to a Service Registry service instance that has one or more peers in another PCF deployment which uses self-signed certificates, you must set the TRUST_CERTS environment variable on your application to a hostname on the other PCF deployment in order for your application to communicate with applications bound to those Service Registry peers:

$ cf set-env message-generation TRUST_CERTS api.cf.otherwise.com
Setting env variable 'TRUST_CERTS' to 'api.cf.otherwise.com' for app message-generation in org myorg / space development as user...
OK
TIP: Use 'cf restage message-generation' to ensure your env variable changes take effect

The TRUST_CERTS environment variable can contain multiple hostnames, in case (e.g.) the Service Registry has peers in multiple alternate PCF deployments with self-signed certificates. Hostnames are comma-separated:

$ cf set-env message-generation TRUST_CERTS api.cf.otherwise.com,api.verywise.com
Setting env variable 'TRUST_CERTS' to 'api.cf.otherwise.com,api.verywise.com' for app message-generation in org myorg / space development as user...
OK
TIP: Use 'cf restage message-generation' to ensure your env variable changes take effect

As the output from the cf set-env command suggests, restage the application after setting the environment variable.

$ cf restage message-generation

Register a Service

To register with a Service Registry service instance, your application must include the @EnableDiscoveryClient annotation on a configuration class.

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class MessageGenerationApplication {
    //...

The application’s Eureka instance name (the name by which it will be registered in Eureka) will be derived from the value of the spring.application.name property on the application. If you do not provide a value for this property, the application’s Eureka instance name will be derived from its Cloud Foundry application name, as set in manifest.yml:

---
instances: 1
memory: 1G
applications:
  - name: message-generation
  ...

Set the spring.application.name property in application.yml:

spring:
  application:
    name: message-generation

Note: If the application name contains characters which are invalid in a hostname, the application will be registered with the Service Registry service instance using the application name with each invalid character replaced by a hyphen (-) character (for example, given an application name of “message_generation”, the Eureka application name used to register the application with the Service Registry service instance will be message-generation). See the Eureka Application Name Configuration section of the Spring Cloud Connectors topic for more information.

Register Using Container-to-Container Networking

To use Cloud Foundry’s container networking (see the Understanding Container-to-Container Networking topic in the Pivotal Cloud Foundry documentation) with the application, your application.yml must specify a spring.cloud.services.registrationMethod of direct.

spring:
  application:
    name: message-generation
  cloud:
    services:
      registrationMethod: direct

Before a client application can use the Service Registry to reach this directly-registered application, you must add a network policy that allows traffic from the client application to this application. See the Consume Using Container-to-Container Networking section for more information.

Consume a Service

Follow the below instructions to consume a service that is registered with a Service Registry service instance.

Discover and Consume a Service Using RestTemplate

A consuming application must include the @EnableDiscoveryClient annotation on a configuration class.

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class GreeterApplication {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Autowired
    private RestTemplate rest;
    //...

To call a registered service, a consuming application can use a URI with a hostname matching the name with which the service is registered in the Service Registry. This way, the consuming application does not need to know the service application’s actual URL; the Registry will take care of finding and routing to the service.

Note: If the name of the registered application contains characters which are invalid in a hostname, that application will be registered with the Service Registry service instance using the application name with each invalid character replaced by a hyphen (-) character. For example, given an application name of “message_generation”, the Eureka application name used to register the application with the Service Registry service instance will be message-generation. See the Eureka Application Name Configuration section of the Spring Cloud Connectors topic for more information.

By default, Service Registry requires HTTPS for access to registered services. If your client application is consuming a service application which has been registered with the Service Registry instance using route registration (see the Register the Application section above), you can use a schemeless URI (as //message-generation) to access the service. Spring Cloud Netflix Ribbon will default to using an HTTPS route if one is available and to an HTTP route otherwise. (This behavior requires Spring Cloud Brixton.SR6 or later.)

The Message Generation application is registered with the Service Registry instance as message-generation, so in the Greeter application, the hello() method on the GreeterApplication class uses the base URI //message-generation to get a greeting message from Message Generation.

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam(value="salutation",
                                        defaultValue="Hello") String salutation,
                        @RequestParam(value="name",
                                        defaultValue="Bob") String name) {
        URI uri = UriComponentsBuilder.fromUriString("//message-generation/greeting")
            .queryParam("salutation", salutation)
            .queryParam("name", name)
            .build()
            .toUri();

        Greeting greeting = rest.getForObject(uri, Greeting.class);
        return greeting.getMessage();
    }

Discover and Consume a Service Using Feign

If you wish to use Feign to consume a service that is registered with a Service Registry instance, your application must declare spring-cloud-starter-feign as a dependency. In order to have Feign client interfaces automatically configured, it must also use the @EnableFeignClients annotation.

Your consuming application must include the @EnableDiscoveryClient annotation on a configuration class. In the Greeter application, the GreeterApplication class contains a MessageGenerationClient interface, which is a Feign client for the Message Generation application.

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@RestController
public class GreeterApplication {

    @Autowired
    MessageGenerationClient messageGeneration;
    //...

To call a registered service, a consuming application can use a URI with a hostname matching the name with which the service is registered in the Service Registry. This way, the consuming application does not need to know the service application’s actual URL; the Registry will take care of finding and routing to the service.

Note: If the name of the registered application contains characters which are invalid in a hostname, that application will be registered with the Service Registry service instance using the application name with each invalid character replaced by a hyphen (-) character. For example, given an application name of “message_generation”, the Eureka application name used to register the application with the Service Registry service instance will be message-generation. See the Eureka Application Name Configuration section of the Spring Cloud Connectors topic for more information.

The Message Generation application is registered with the Service Registry instance as message-generation, so the @FeignClient annotation on the MessageGenerationClient interface uses the base URI http://message-generation. The interface declares one method, greeting(), which accesses the Message Generation application’s /greeting endpoint and sends along optional name and salutation parameters if they are provided.

    @FeignClient("http://message-generation")
    interface MessageGenerationClient {
      @RequestMapping(value = "/greeting", method = GET)
      Greeting greeting(@RequestParam("name") String name, @RequestParam("salutation") String salutation);
    }

Consume Using Container-to-Container Networking

To use Cloud Foundry’s container networking (see the Understanding Container-to-Container Networking topic in the Pivotal Cloud Foundry documentation) to reach an application registered with the Service Registry, you must add a network policy. You can do this using the Networking cf CLI plugin.

Run the cf list-access command to list current network policies:

$ cf list-access
Listing policies as user...
OK

Source    Destination    Protocol    Port

Use the cf allow-access command to grant access from the Greeter application to the Message Generation application:

$ cf allow-access greeter message-generation --protocol tcp --port 8080
Allowing traffic from greeter to message-generation as user...
OK

Use cf list-access again to view the new access policy:

$ cf list-access
Listing policies as user...
OK

Source        Destination           Protocol   Port
greeter       message-generation    tcp        8080

The Greeter application can now use container networking to access the Message Generation application via the Service Registry. For more information about configuring container networking, see the Administering Container-to-Container Networking topic in the Pivotal Cloud Foundry documentation.

Disable HTTP Basic Authentication

The Spring Cloud Services Starter for Service Registry has a dependency on Spring Security. Unless your application has other security configuration, this will cause all application endpoints to be protected by HTTP Basic authentication.

If you do not yet want to address application security, you may turn off Basic authentication by setting the security.basic.enabled property to false. In application.yml or bootstrap.yml:

security:
  basic:
    enabled: false

You might make this setting specific to a profile (such as the dev profile if you want Basic authentication disabled only for development):

---

spring:
  profiles: dev

security:
  basic:
    enabled: false

For more information, see “Security” in the Spring Boot Reference Guide.

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