LATEST VERSION: 2.0 - RELEASE NOTES
Spring Cloud Services v2.0

Writing Client Applications

Page last updated:

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

To use a Spring app with a Service Registry service instance, you must add the dependencies listed in Client Dependencies to your app’s build file. Be sure to include the dependencies for Service Registry as well.

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) foundation is using a self-signed SSL certificate, the certificate will need to be added to the JVM truststore before your app 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 app to the API endpoint of your Pivotal Application Service (PAS) or 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 app after setting the environment variable.

Service Registry Peers with Self-Signed Certificates

If binding your app to a Service Registry service instance that has one or more peers in another PCF foundation which uses self-signed certificates, you must set the TRUST_CERTS environment variable on your app to a hostname on the other PCF foundation in order for your app to communicate with apps 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 (for example) the Service Registry has peers in multiple alternate PCF foundations 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 app after setting the environment variable.

$ cf restage message-generation

Register a Service

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

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

The app’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 app. If you do not provide a value for this property, the app’s Eureka instance name will be derived from its Cloud Foundry application name, as set in manifest.yml:

---
applications:
  - name: greeter-messages
    instances: 1
    memory: 1G
  ...

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

spring:
  application:
    name: greeter-messages

Note: If the application name contains characters which are invalid in a hostname, the app 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 “greeter_messages”, the Eureka application name used to register the app with the Service Registry service instance will be greeter-messages). See Eureka Application Name Configuration.

Register Using Container-to-Container Networking

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

spring:
  application:
    name: greeter-messages
  cloud:
    services:
      registrationMethod: direct

Before a client app can use the Service Registry to reach this directly-registered app, you must add a network policy that allows traffic from the client app to this app. 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 app must include the @EnableDiscoveryClient annotation on a configuration class.

@SpringBootApplication
@EnableDiscoveryClient
public class GreeterApplication {

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

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

Note: If the name of the registered app contains characters which are invalid in a hostname, that app 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 “greeter_messages”, the Eureka application name used to register the app with the Service Registry service instance will be greeter-messages. See Eureka Application Name Configuration.

By default, Service Registry requires HTTPS for access to registered services. If your client app is consuming a service app which has been registered with the Service Registry instance using route registration (see the Register a Service section above), you can use a schemeless URI (as //greeter-messages) 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.

The Messages app is registered with the Service Registry as greeter-messages, so the Greeter app uses the base URI /greeter-messages to communicate with Messages.

@Service
public class GreeterService {

  private static final String URI_TEMPLATE = UriComponentsBuilder.fromUriString("//greeter-messages/greeting")
      .queryParam("salutation", "{salutation}")
      .queryParam("name", "{name}")
      .build()
      .toUriString();

The Greeter app uses a Greeting class to contain the response from Messages:

public class Greeting {

  private String message;

  @JsonCreator
  public Greeting(@JsonProperty("message") String message) {
    this.message = message;
  }

  public String getMessage() {
    return this.message;
  }

}

The greet() method of the GreeterService uses a RestTemplate to return a Greeting.

  public Greeting greet(String salutation, String name) {
    //...
    return rest.getForObject(URI_TEMPLATE, Greeting.class, salutation, name);
  }

Finally, the GreeterController maps its hello() method to /hello, and passes received request parameters to the GreeterService to get a greeting message to return to the user.

  @RequestMapping(value = "/hello", method = RequestMethod.GET)
  public String hello(@RequestParam(value = "salutation", defaultValue = "Hello") String salutation, @RequestParam(value = "name", defaultValue = "Bob") String name) {
    Greeting greeting = greeter.greet(salutation, name);
    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 app must declare spring-cloud-starter-openfeign as a dependency.

Using Maven:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Using Gradle:

compile("org.springframework.cloud:spring-cloud-starter-openfeign")

Your consuming app must include the @EnableDiscoveryClient annotation on a configuration class. In order to have Feign client interfaces automatically configured, it must also use the @EnableFeignClients annotation.

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

    @Autowired
    MessagesClient messagesClient;
    //...

The Greeter app uses a Greeting class to contain the response from Messages:

public class Greeting {

  private String message;

  @JsonCreator
  public Greeting(@JsonProperty("message") String message) {
    this.message = message;
  }

  public String getMessage() {
    return this.message;
  }
}

The GreeterApplication class has a method hello() which is mapped to /hello and uses a Feign client to access the Messages app.

    @RequestMapping(value = "/hello", method = GET)
    public String hello(@RequestParam(value="salutation", defaultValue="Hello") String salutation, @RequestParam(value="name", defaultValue="Bob") String name) {
      Greeting greeting =  messagesClient.greeting(name, salutation);
      return greeting.getMessage();
    }

In the Greeter app, the MessagesClient interface is a Feign client for the Messages app:

@FeignClient("greeter-messages")
interface MessagesClient {
  @RequestMapping(value = "/greeting", method = GET)
  Greeting greeting(@RequestParam("name") String name, @RequestParam("salutation") String salutation);
}

The Messages app is registered with the Service Registry instance as greeter-messages, so the @FeignClient annotation on the MessagesClient interface uses that Eureka application name. The interface declares one method, greeting(), which accesses the Messages app’s /greeting endpoint and sends along optional name and salutation parameters if they are provided.

Note: If the name of the registered app contains characters which are invalid in a hostname, that app 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 app with the Service Registry service instance will be greeter-messages. See Eureka Application Name Configuration.

Consume Using Container-to-Container Networking

To use Cloud Foundry’s container networking (see Understanding Container-to-Container Networking in the Pivotal Cloud Foundry documentation) to reach an app 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 app to the Messages app:

$ cf add-network-policy greeter --destination-app greeter-messages --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   greeter-messages   tcp        8080

The Greeter app can now use container networking to access the Messages app via the Service Registry. For more information about configuring container networking, see Administering Container-to-Container Networking 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 app has other security configuration, this will cause all app endpoints to be protected by HTTP Basic authentication.

If you do not yet want to address application security, you may turn off Basic authentication using a class that extends Spring Security’s WebSecurityConfigurerAdapter and is annotated with the Spring @Configuration annotation. The sample apps disable all default security for the development profile only, using the @Profile annotation:

@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 Reference Guide.

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