Permalink
Fetching contributors…
Cannot retrieve contributors at this time
423 lines (320 sloc) 20.6 KB
---
title: Configuring Service Connections for Spring
owner: Java
---
<strong><%= modified_date %></strong>
Cloud Foundry provides extensive support for connecting a Spring application to services such as MySQL, PostgreSQL, MongoDB, Redis, and RabbitMQ. In many cases, Cloud Foundry can automatically configure a Spring application without any code changes. For more advanced cases, you can control service connection parameters yourself.
## <a id='auto'></a>Auto-Reconfiguration ##
If your Spring application requires services such as a relational database or messaging system, you might be able to deploy your application to Cloud Foundry without changing any code. In this case, Cloud Foundry automatically re-configures the relevant bean definitions to bind them to cloud services.
For information about connecting to services from a Spring application, see
[Spring Cloud Spring Service Connector](http://cloud.spring.io/spring-cloud-connectors/spring-cloud-spring-service-connector.html).
Cloud Foundry auto-reconfigures applications only if the following items are true for your application:
* Only one service instance of a given service type is bound to the application. In this context, different relational databases services are considered the same service type. For example, if both a MySQL and a PostgreSQL service are bound to the application, auto-reconfiguration does not occur.
* Only one bean of a matching type is in the Spring application context. For example, you can have only one bean of type `javax.sql.DataSource`.
With auto-reconfiguration, Cloud Foundry creates the `DataSource` or connection factory bean itself, using its own values for properties such as host, port, and username. For example, if you have a single `javax.sql.DataSource` bean in your application context that Cloud Foundry auto-reconfigures and binds to its own database service, Cloud Foundry does not use the username, password, and driver URL you originally specified. Instead, Cloud Foundry uses its own internal values. This is transparent to the app, which really only cares about having a `DataSource` where it can write data but does not really care what the specific properties are that created the database. Also, if you have customized the configuration of a service, such as the pool size or connection properties, Cloud Foundry auto-reconfiguration ignores the customizations.
For more information about auto-reconfiguration of specific services types, see the [Service-Specific Details](#services) section.
## <a id='manual'></a>Manual Configuration ##
Use manual configuration if you have multiple services of a given type or you
want to have more control over the configuration than auto-reconfiguration
provides.
To use manual configuration, include the `spring-cloud` library in your
list of application dependencies.
Update your application Maven `pom.xml` or Gradle `build.gradle` file to include
dependencies on the
`org.springframework.cloud:spring-cloud-spring-service-connector` and
`org.springframework.cloud:spring-cloud-cloudfoundry-connector` artifacts.
For example, if you use Maven to build your application, the following `pom.xml`
snippet shows how to add this dependency.
```xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
<version>1.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.2.3.RELEASE</version>
</dependency>
</dependencies>
```
You also need to update your application build file to include the Spring Framework Milestone repository. The following `pom.xml` snippet shows how to do this for Maven:
```xml
<repositories>
<repository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>
...
</repositories>
```
### <a id='javaconfig'></a>Java Configuration ###
Typical use of Java config involves extending the `AbstractCloudConfig` class and adding methods with the `@Bean` annotation to create beans for services. Apps migrating from [auto-reconfiguration](http://spring.io/blog/2011/11/04/using-cloud-foundry-services-with-spring-part-2-auto-reconfiguration/) might first try [Scanning for Services](#scan-services) until they need more explicit control.
Java config also offers a way to expose application and service properties. Use this for debugging or to create service connectors using a lower-level access.
#### <a id='create-service-beans'></a>Create a Service Bean ####
In the following example, the configuration creates a `DataSource` bean connecting to the only relational database service bound to the app. It also creates a `MongoDbFactory` bean, again, connecting to the only MongoDB service bound to the app. Check Javadoc for `AbstractCloudConfig` for ways to connect to other services.
```java
class CloudConfig extends AbstractCloudConfig {
@Bean
public DataSource inventoryDataSource() {
return connectionFactory().dataSource();
}
... more beans to obtain service connectors
}
```
The bean names match the method names unless you specify an explicit value to the annotation such as `@Bean("inventory-service")`, following Spring's Java configuration standards.
If you have more than one service of a type bound to the app or want to have an
explicit control over the services to which a bean is bound, you can pass the service names to methods such as `dataSource()` and `mongoDbFactory()` as follows:
```java
class CloudConfig extends AbstractCloudConfig {
@Bean
public DataSource inventoryDataSource() {
return connectionFactory().dataSource("inventory-db-service");
}
@Bean
public MongoDbFactory documentMongoDbFactory() {
return connectionFactory().mongoDbFactory("document-service");
}
... more beans to obtain service connectors
}
```
Method such as `dataSource()` come in an additional overloaded variant that offer specifying configuration options such as the pooling parameters. See Javadoc for more details.
#### <a id='connect-gen-services'></a>Connect to Generic Services ####
Java config supports access to generic services through the `service()` method.
Generic services do not have a directly mapped method. This is typical for a newly introduced service or when connecting to a private service in private PaaS. The generic `service()` method follows the same pattern as the
`dataSource()`, except it allows supplying the connector type as an additional
parameters.
#### <a id='scan-services'></a>Scan for Services ####
You can scan for each bound service using the `@ServiceScan` annotation as shown below. This is conceptually similar to the @ComponentScan annotation in Spring:
```java
@Configuration
@ServiceScan
class CloudConfig {
}
```
Here, one bean of the appropriate type (`DataSource` for a relational database
service, for example) is created. Each created bean will have the `id` matching
the corresponding service name. You can then inject such beans using auto-wiring:
```java
@Autowired DataSource inventoryDb;
```
If the app is bound to more than one services of a type, you can use the `@Qualifier` annotation supplying it the name of the service as in the following code:
```java
@Autowired @Qualifier("inventory-db") DataSource inventoryDb;
@Autowired @Qualifier("shipping-db") DataSource shippingDb;
```
#### <a id='access-service-providers'></a>Access Service Properties ####
You can expose raw properties for all services and the app through a bean as follows:
```java
class CloudPropertiesConfig extends AbstractCloudConfig {
@Bean
public Properties cloudProperties() {
return properties();
}
}
```
## <a id='cloud-profiles'></a>Cloud Profile ##
Spring Framework versions 3.1 and above support bean definition profiles as a way to conditionalize the application configuration so that only specific bean definitions are activated when a certain condition is true. Setting up such profiles makes your application portable to many different environments so that you do not have to manually change the configuration when you deploy it to, for example, your local environment and then to Cloud Foundry.
See the Spring Framework documentation for additional information about using Spring bean definition profiles.
When you deploy a Spring application to Cloud Foundry, Cloud Foundry automatically enables the `cloud` profile.
<p class="note"><strong>Note</strong>: Cloud Foundry auto-reconfiguration requires the Spring application to be version 3.1 or later and include the Spring context JAR. If you are using an earlier version, update your framework or use a custom buildpack.</p>
### <a id='cloud-profiles-java'></a>Profiles in Java Configuration ###
The `@Profile` annotation can be placed on `@Configuration` classes in a Spring
application to set conditions under which configuration classes are invoked. By using the `default` and `cloud` profiles to determine whether the application is running on Cloud Foundry or not, your Java configuration can support both local and cloud deployments using Java configuration classes like these:
```
public class Configuration {
@Configuration
@Profile("cloud")
static class CloudConfiguration {
@Bean
public DataSource dataSource() {
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
String serviceID = cloud.getServiceID();
return cloud.getServiceConnector(serviceID, DataSource.class, null);
}
}
@Configuration
@Profile("default")
static class LocalConfiguration {
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:postgresql://localhost/db");
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUsername("postgres");
dataSource.setPassword("postgres");
return dataSource;
}
}
}
```
## <a id='properties'></a>Property Placeholders ##
Cloud Foundry exposes a number of application and service properties directly into its deployed applications. The properties exposed by Cloud Foundry include basic information about the application, such as its name and the cloud provider, and detailed connection information for all services currently bound to the application.
Service properties generally take one of the following forms:
```bash
cloud.services.{service-name}.connection.{property}
cloud.services.{service-name}.{property}
```
In this form, `{service-name}` refers to the name you gave the service when you bound it to your application at deploy time, and `{property}` is a field in the credentials section of the `VCAP_SERVICES` environment variable.
For example, assume that you created a Postgres service called `my-postgres` and then bound it to your application. Assume also that this service exposes credentials in `VCAP_SERVICES` as discrete fields. Cloud Foundry exposes the following properties about this service:
```bash
cloud.services.my-postgres.connection.hostname
cloud.services.my-postgres.connection.name
cloud.services.my-postgres.connection.password
cloud.services.my-postgres.connection.port
cloud.services.my-postgres.connection.username
cloud.services.my-postgres.plan
cloud.services.my-postgres.type
```
If the service exposed the credentials as a single `uri` field, then the following properties would be set up:
```bash
cloud.services.my-postgres.connection.uri
cloud.services.my-postgres.plan
cloud.services.my-postgres.type
```
For convenience, if you have bound just one service of a given type to your
application, Cloud Foundry creates an alias based on the service type instead of the
service name. For example, if only one MySQL service is bound to an application, the
properties takes the form `cloud.services.mysql.connection.{property}`. Cloud
Foundry uses the following aliases in this case:
* `mysql`
* `postgresql`
* `mongodb`
* `redis`
* `rabbitmq`
A Spring application can take advantage of these Cloud Foundry properties using the property placeholder mechanism. For example, assume that you have bound a MySQL service called `spring-mysql` to your application. Your application requires a `c3p0` connection pool instead of the connection pool provided by Cloud Foundry, but you want to use the same connection properties defined by Cloud Foundry for the MySQL service - in particular the username, password and JDBC URL.
The following table lists all the application properties that Cloud Foundry exposes to deployed applications.
| Property | Description
| ------------------------ |------------
| `cloud.application.name` | The name provided when the application was pushed to Cloud Foundry.
| `cloud.provider.url` | The URL of the cloud hosting the application, such as `cloudfoundry.com`.
The service properties that are exposed for each type of service are listed in the [Service-Specific Details](#services) section.
## <a id='services'></a>Service-Specific Details ##
The following sections describe Spring auto-reconfiguration and manual configuration for the services supported by Cloud Foundry.
### <a id='rdbms'></a>MySQL and Postgres ###
#### <a id='mysql-auto-reconfig'></a>Auto-Reconfiguration ####
Auto-reconfiguration occurs if Cloud Foundry detects a `javax.sql.DataSource` bean in the Spring application context. The following snippet of a Spring application context file shows an example of defining this type of bean which Cloud Foundry will detect and potentially auto-reconfigure:
```xml
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
```
The relational database that Cloud Foundry actually uses depends on the service instance you explicitly bind to your application when you deploy it: MySQL or Postgres. Cloud Foundry creates either a commons DBCP or Tomcat datasource depending on which datasource implementation it finds on the classpath.
Cloud Foundry internally generates values for the following properties: `driverClassName`, `url`, `username`, `password`, `validationQuery`.
#### <a id='mysql-man-java-reconfig'></a>Manual Configuration in Java ####
To configure a database service in Java configuration, create a `@Configuration` class with a `@Bean` method to return a `javax.sql.DataSource` bean. The bean can be created by helper classes in the `spring-cloud` library, as shown here:
```
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
String serviceID = cloud.getServiceID();
return cloud.getServiceConnector(serviceID, DataSource.class, null);
}
}
```
### <a id='mongodb'></a>MongoDB ###
#### <a id='mongodb-auto-reconfig'></a>Auto-Reconfiguration ####
You must use Spring Data MongoDB 1.0 M4 or later for auto-reconfiguration to work.
Auto-reconfiguration occurs if Cloud Foundry detects an `org.springframework.data.document.mongodb.MongoDbFactory` bean in the Spring application context. The following snippet of a Spring XML application context file shows an example of defining this type of bean which Cloud Foundry will detect and potentially auto-reconfigure:
```xml
<mongo:db-factory
id="mongoDbFactory"
dbname="pwdtest"
host="127.0.0.1"
port="1234"
username="test_user"
password="test_pass" />
```
Cloud Foundry creates a `SimpleMongoDbFactory` with its own values for the following properties: `host`, `port`, `username`, `password`, `dbname`.
#### <a id='mongodb-man-java-reconfig'></a>Manual Configuration in Java ####
To configure a MongoDB service in Java configuration, create a `@Configuration` class with a `@Bean` method to return an `org.springframework.data.mongodb.MongoDbFactory` bean from Spring Data MongoDB. The bean can be created by helper classes in the `spring-cloud` library, as shown here:
```
@Configuration
public class MongoConfig {
@Bean
public MongoDbFactory mongoDbFactory() {
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
MongoServiceInfo serviceInfo = (MongoServiceInfo) cloud.getServiceInfo("my-mongodb");
String serviceID = serviceInfo.getID();
return cloud.getServiceConnector(serviceID, MongoDbFactory.class, null);
}
@Bean
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoDbFactory());
}
}
````
### <a id='redis'></a>Redis ###
#### <a id='redis-auto-reconfig'></a>Auto-Configuration ####
You must be using Spring Data Redis 1.0 M4 or later for auto-configuration to work.
Auto-configuration occurs if Cloud Foundry detects a `org.springframework.data.redis.connection.RedisConnectionFactory` bean in the Spring application context. The following snippet of a Spring XML application context file shows an example of defining this type of bean which Cloud Foundry will detect and potentially auto-configure:
```xml
<bean id="redis"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:hostName="localhost" p:port="6379" />
```
Cloud Foundry creates a `JedisConnectionFactory` with its own values for the following properties: `host`, `port`, `password`. This means that you must package the Jedis JAR in your application. Cloud Foundry does not currently support the JRedis and RJC implementations.
#### <a id='redis-man-java-reconfig'></a>Manual Configuration in Java ####
To configure a Redis service in Java configuration, create a `@Configuration` class with a `@Bean` method to return an `org.springframework.data.redis.connection.RedisConnectionFactory` bean from Spring Data Redis. The bean can be created by helper classes in the `spring-cloud` library, as shown here:
```
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
RedisServiceInfo serviceInfo = (RedisServiceInfo) cloud.getServiceInfo("my-redis");
String serviceID = serviceInfo.getID();
return cloud.getServiceConnector(serviceID, RedisConnectionFactory.class, null);
}
@Bean
public RedisTemplate redisTemplate() {
return new StringRedisTemplate(redisConnectionFactory());
}
}
```
### <a id='rabbitmq'></a>RabbitMQ ###
#### <a id='rabbitmq-auto-reconfig'></a>Auto-Configuration ####
You must be using Spring AMQP 1.0 or later for auto-configuration to work. Spring AMQP provides publishing, multi-threaded consumer generation, and message conversion. It also facilitates management of AMQP resources while promoting dependency injection and declarative configuration.
Auto-configuration occurs if Cloud Foundry detects an `org.springframework.amqp.rabbit.connection.ConnectionFactory` bean in the Spring application context. The following snippet of a Spring application context file shows an example of defining this type of bean which Cloud Foundry will detect and potentially auto-configure:
```xml
<rabbit:connection-factory
id="rabbitConnectionFactory"
host="localhost"
password="testpwd"
port="1238"
username="testuser"
virtual-host="virthost" />
```
Cloud Foundry creates an `org.springframework.amqp.rabbit.connection.CachingConnectionFactory` with its own values for the following properties: `host`, `virtual-host`, `port`, `username`, `password`.
#### <a id='rabbitmq-man-java-reconfig'></a>Manual Configuration in Java ####
To configure a RabbitMQ service in Java configuration, create a
`@Configuration` class with a `@Bean` method to return an
`org.springframework.amqp.rabbit.connection.ConnectionFactory` bean from the Spring AMQP library. The bean can be created by helper classes in the `spring-cloud` library, as shown here:
```
@Configuration
public class RabbitConfig {
@Bean
public ConnectionFactory rabbitConnectionFactory() {
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
AmqpServiceInfo serviceInfo = (AmqpServiceInfo) cloud.getServiceInfo("my-rabbit");
String serviceID = serviceInfo.getID();
return cloud.getServiceConnector(serviceID, ConnectionFactory.class, null);
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
}
```