To use a Spring Cloud Services 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.
Refer to the sample apps in the "greeting" repository to follow along with the code in this topic.
Spring Cloud Services uses HTTPS for all client-to-service communication. If your VMware Tanzu Application Service for VMs 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 VMware Tanzu Application Service for VMs (TAS for VMs) instance:
$ cf set-env message-generation TRUST_CERTS api.cf.example.com
Setting env variable 'TRUST_CERTS' to 'api.cf.example.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.
If binding your app to a Service Registry service instance that has one or more peers in another TAS foundation which uses self-signed certificates, you must set the TRUST_CERTS
environment variable on your app to a hostname on the other TAS 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.example.org
Setting env variable 'TRUST_CERTS' to 'api.cf.example.org' 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 TAS foundations with self-signed certificates. Hostnames are comma-separated:
$ cf set-env message-generation TRUST_CERTS api.cf.example.org,api.example.net
Setting env variable 'TRUST_CERTS' to 'api.cf.example.org,api.example.net' 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
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.
To use Cloud Foundry's container networking (see Container-to-Container Networking) 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.
Follow the below instructions to consume a service that is registered with a Service Registry service instance.
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();
}
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.
To use Cloud Foundry's container networking (see Container-to-container networking) 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.
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 is annotated with the Spring @Configuration
annotation. The sample apps deactivate all default security for the development
profile only, using the @Profile
annotation:
@Configuration
@Profile("development")
public class SecurityConfiguration {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests().anyRequest().permitAll()
.and()
.httpBasic().disable()
.csrf().disable()
.build();
}
}
For more information, see Security in the Spring Boot Reference Guide.