LATEST VERSION: 2.0 - RELEASE NOTES
Spring Cloud Services v1.5

Writing Client Applications

Page last updated:

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

To use a Spring Boot app as a client for a Service Registry instance, you must add the dependencies listed below.

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 following BOMs:

  • spring-cloud-services-dependencies
  • spring-cloud-dependencies
  • spring-boot-dependencies, unless you use spring-boot-starter-parent (with Maven) or the Spring Boot Gradle plugin (with Gradle)

See the following sections for how to construct a build file for your use case.

General Dependencies

Construct your build file using one of the examples below, for either Maven or Gradle. Replace [BOOT], [CLOUD], and [SCS] according to your Spring Boot and Spring Cloud version. Refer to the following table:

If using… …use [BOOT] …use [CLOUD] …use [SCS]
Boot 2, Cloud Finchley 2.0.3.RELEASE Finchley.RELEASE 2.0.1.RELEASE
Boot 1.5, Cloud Edgware 1.5.13.RELEASE Edgware.SR3 1.6.1.RELEASE

For Maven

If using Maven, include in pom.xml:

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>[BOOT]</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.pivotal.spring.cloud</groupId>
            <artifactId>spring-cloud-services-dependencies</artifactId>
            <version>[SCS]</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>[CLOUD]</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>[BOOT]</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- ... -->

    </dependencies>
  </dependencyManagement>

For Gradle

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:1.0.5.RELEASE")
        classpath("org.springframework.boot:spring-boot-gradle-plugin:[BOOT]")
    }
}

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

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:[CLOUD]"
        mavenBom "io.pivotal.spring.cloud:spring-cloud-services-dependencies:[SCS]"
    }
}

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:[BOOT]"
    }
}
Your app must also declare the Spring Cloud Services Service Registry starter as a 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")
}

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 Cloud Foundry Command Line Interface (cf CLI).

Note: Container networking support is included in the cf CLI version 6.30.0 and later.

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

$ cf network-policies
Listing network policies in org myorg / space dev as user...

source   destination   protocol   ports

Use the cf add-network-policy command to grant access from the Greeter application to the Message Generation application:

$ cf add-network-policy greeter --destination-app message-generation --protocol tcp --port 8080
Adding network policy to app greeter in org myorg / space dev as user...
OK

Use cf network-policies again to view the new access policy:

$ cf network-policies
Listing network policies in org myorg / space dev as user...

source    destination          protocol   ports
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 can disable Basic authentication. See below for information about doing this in your app’s version of Spring Boot.

Using Spring Boot 1.5

If you are using Spring Boot 1.5, you can disable HTTP Basic authentication by setting the security.basic.enabled property to false in bootstrap.yml or application.yml. 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 1.5 Reference Guide.

Note: Because of the Spring Security dependency, HTTPS Basic authentication will also be enabled for Spring Boot Actuator endpoints. If you wish to disable that as well, you must also set the management.security.enabled property to false. See “Customizing the management server port” in the Spring Boot 1.5 Reference Guide.

Using Spring Boot 2.0

If you are using Spring Boot 2.0, you can disable HTTP Basic authentication using a class that extends Spring Security’s WebSecurityConfigurerAdapter and is annotated with the Spring @Configuration annotation. To do so, you must include the Spring Boot Security starter in your build file.

Using Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Using Gradle:

compile("org.springframework.boot:spring-boot-starter-security")

The following class disables all default security for the development profile only, using the @Profile annotation:

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@Profile("development")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().anyRequest().permitAll()
                .and()
                .httpBasic().disable()
                .csrf().disable();
    }

}

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

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