In this lab we’ll utilize Spring Boot and Spring Cloud to configure our application from a configuration dynamically retrieved from a git repository. We’ll then deploy it to Pivotal Cloud Foundry and auto-provision an instance of a configuration server using Pivotal Spring Cloud Services.
-
These features are added by adding spring-cloud-services-starter-config-client to the classpath. Open your Maven POM found here: /cloud-native-spring/pom.xml. Add the following spring cloud services dependency:
<dependency> <groupId>io.pivotal.spring.cloud</groupId> <artifactId>spring-cloud-services-starter-config-client</artifactId> </dependency>
-
We also need to add a general entry for Spring Cloud dependency management. Add this snippet to your POM:
<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.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
Add an @Value annotation, private field, and associated usage to the class io.pivotal.CloudNativeSpringApplication (/cloud-native-spring/src/main/java/io/pivotal/CloudNativeSpringApplication.java):
@Value("${greeting:Hola}") private String _greeting; @RequestMapping("/") public String hello() { return _greeting + " World!"; }
Completed:
package io.pivotal; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration; import org.springframework.context.annotation.Import; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController @EnableJpaRepositories @Import(RepositoryRestMvcAutoConfiguration.class) public class CloudNativeSpringApplication { public static void main(String[] args) { SpringApplication.run(CloudNativeSpringApplication.class, args); } @Value("${greeting:Hola}") private String _greeting; @RequestMapping("/") public String hello() { return _greeting + " World!"; } }
-
When we introduced the Spring Cloud Services Starter Config Client dependency Spring Security will also be included (Config servers will be protected by OAuth2). However, this will also enable basic authentication to all our service endpoints. Add the following configuration to /cloud-native-spring/src/main/resources/application.yml:
security: basic: enabled: false
-
We’ll also want to give our Spring Boot App a name so that it can lookup application-specific configuration from the config server later. Add the following configuration to /cloud-native-spring/src/main/resources/application.yml:
spring: application: name: cloud-native-spring
-
Complete YML:
spring: application: name: cloud-native-spring endpoints: # add this section sensitive: false info: # add this section build: artifact: @project.artifactId@ name: @project.name@ description: @project.description@ version: @project.version@ management: security: enabled: false info: git: mode: full cloudfoundry: enabled: true skip-ssl-validation: true security: basic:
-
Run the application
$ mvn clean spring-boot:run
-
Browse to http://localhost:8080 and verify you now see your new greeting.
-
Stop the cloud-native-spring application
-
Now that our application is ready to read its config from a cloud config server, we need to deploy one! This can be done through cloudfoundry using the services marketplace. Browse to the marketplace in Pivotal Cloudfoundry Apps Manager, https://apps.cfpoc2.internal.t-mobile.com, navigate to the space you have been using to push your app, and select Config Server:
-
In the resulting details page, select the standard, single tenant plan. Name the instance config-server, select the space that you’ve been using to push all your applications. At this time you don’t need to select a application to bind to the service:
-
After we create the service instance you’ll be redirected to your Space landing page that lists your apps and services. The config server is deployed on-demand and will take a few moments to deploy. Once the messsage The Service Instance is Initializing disappears click on the service you provisioned. Select the manage link towards the top of the resulting screen to view the instance id and a JSON document with a single element, count, which validates that the instance provisioned correctly:
-
We now need to update the service instance with our GIT repository information. Using the cloudfoundry CLI execute the following update service command:
$ cf update-service config-server -c '{"git": { "uri": "https://github.com/azwickey-pivotal/config-repo" } }'
-
Refresh you Config Server management page and you will see the following message. Wait until the screen refreshes and the service is reintialized:
-
We will now bind our application to our config-server within our Cloudfoundry deployment manifest. Add these 2 entries to the bottom of /cloud-native-spring/manifest.yml
env: TRUST_CERTS: api.cfpoc2.internal.t-mobile.com services: - config-server
Complete:
--- applications: - name: cloud-native-spring host: cloud-native-spring memory: 512M instances: 1 path: ./target/cloud-native-spring-0.0.1-SNAPSHOT.jar buildpack: java_buildpack_offline timeout: 180 env: TRUST_CERTS: https://api.cfpoc2.internal.t-mobile.com JAVA_OPTS: -Djava.security.egd=file:///dev/urandom services: - config-server
-
Build the application
$ mvn clean package
-
Push application into Cloud Foundry
$ cf push -f manifest.yml
-
Test your application by navigating to the root URL of the application, which will invoke the hello() service. You should now see a greeting that is read from the cloud config server!
Bon Jour World!
-
What just happened?? A Spring component within the Spring Cloud Starter Config Client module called a service connector automatically detected that there was a Cloud Config service bound into the application. The service connector configured the application automatically to connect to the cloud config server and download the configuration and wire it into the application
-
If you navigate to the GIT repo we specified for our configuration, https://github.com/azwickey-pivotal/config-repo, you’ll see a file named cloud-native-spring.yml. This filename is the same as our spring.application.name value for our Boot application. The configuration is read from this file, in our case the following property:
greeting: Bon Jour
-
Next we’ll learn how to register our service with a service registry and load balance requests using Spring Cloud components.