Writing Client Applications

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")
}
## Register a Service To register with a Service Registry service instance, your application must include the “`@EnableDiscoveryClient”` annotation on a configuration class. “`java @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`: “`yml — instances: 1 memory: 1G applications: - name: message-generation … ”` Set the `spring.application.name` property in `application.yml`: “`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](https://docs.pivotal.io/pivotalcf/concepts/understand-cf-networking.html) topic in the [Pivotal Cloud Foundry](https://docs.pivotal.io/pivotalcf/) documentation) with the application, your `application.yml` must specify a `spring.cloud.services.registrationMethod` of `direct`. “`yml 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](/spring-cloud-services/service-registry/writing-client-applications.html#consume-using-c2c) 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. “`java @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. “`java @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](https://github.com/Netflix/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. ”`java @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. “`java @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](https://docs.pivotal.io/pivotalcf/concepts/understand-cf-networking.html) topic in the [Pivotal Cloud Foundry](https://docs.pivotal.io/pivotalcf/) 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