From 25caba87a93736fe6151f0538af48f4b175ea765 Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Fri, 14 Aug 2015 12:28:39 -0500 Subject: [PATCH 1/6] minor changes to Spring Service Connector doc; list supported services Adding a listing of services for which SSC provides connection methods, and documentation / examples for how to use them in different ways (configure service, connect to particular service, etc.). --- ...spring-cloud-spring-service-connector.adoc | 130 +++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc b/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc index 20af576..8de0fa2 100644 --- a/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc +++ b/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc @@ -13,7 +13,14 @@ This library provides `ServiceConnectorCreator` implementations for `javax.sql.D == The Java Configuration -Typical use of the Java configuration involves extending the `AbstractCloudConfig` class and creating beans for services by annotating methods with the `@Bean` annotation. (If you are migrating an application that uses link:https://spring.io/blog/2011/11/04/using-cloud-foundry-services-with-spring-part-2-auto-reconfiguration/[auto-reconfiguration], you might first try the <<_scanning_for_services,service-scanning approach>> until you need more explicit control.) The Spring Service Connector Java configuration also offers a way to expose application and service properties in case you want lower-level access when creating your own service connectors (or for debugging purposes, etc.). +Typical use of the Java configuration involves extending the `AbstractCloudConfig` class and creating beans for services by annotating methods with the `@Bean` annotation. + +[TIP] +==== +If you are migrating an application that uses link:https://spring.io/blog/2011/11/04/using-cloud-foundry-services-with-spring-part-2-auto-reconfiguration/[auto-reconfiguration], you might first try the <<_scanning_for_services,service-scanning approach>> until you need more explicit control. +==== + +The Spring Service Connector Java configuration also offers a way to expose application and service properties in case you want lower-level access when creating your own service connectors (or for debugging purposes, etc.). === Creating Service Beans @@ -64,7 +71,126 @@ class CloudConfig extends AbstractCloudConfig { } ---- -Methods such as `dataSource()` come in additional overloaded variants that let you specify configuration options (such as pooling parameters). See the relevant Javadocs for more information. +Out of the box, the Spring Service Connector provides methods for connecting to a variety of services. For information on creating connections to supported services, see below. + +==== RabbitMQ + +To connect to a unique RabbitMQ service, create a service bean using `rabbitConnectionFactory()`. The following example connects to the only RabbitMQ service bound to the application. + +[source,java] +---- +//Connect to the only available RabbitMQ service +@Bean +public RabbitConnectionFactory rabbitFactory() { + return connectionFactory().rabbitConnectionFactory(); +} +---- + +To connect to a specific RabbitMQ service, you can use an overloaded variant of `rabbitConnectionFactory()`. The following example connects specifically to the `bunnymq` RabbitMQ service. + +[source,java] +---- +//Connect to the 'bunnymq' RabbitMQ service +@Bean +public RabbitConnectionFactory rabbitFactory() { + return connectionFactory().rabbitConnectionFactory("bunnymq"); +} +---- + +To provide configuration for a RabbitMQ service, you can use an overloaded `rabbitConnectionFactory()` variant. The following example connects to the `bunnymq` RabbitMQ service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/messaging/RabbitConnectionFactoryConfig.html[`RabbitConnectionFactoryConfig`], which is initialized with a `channelCacheSize` of 10. + +[source,java] +---- +//Connect to the 'bunnymq' RabbitMQ service, supplying configuration +@Bean +public RabbitConnectionFactory rabbitFactory() { + RabbitConnectionFactoryConfig rabbitConfig = new RabbitConnectionFactoryConfig(10); + return connectionFactory().rabbitConnectionFactory("bunnymq", rabbitConfig); +} +---- + +To set properties on a RabbitMQ service, you can use an overloaded variant of `rabbitConnectionFactory()`. The following example connects to the `bunnymq` RabbitMQ service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/messaging/RabbitConnectionFactoryConfig.html[`RabbitConnectionFactoryConfig`], which is initialized with a `HashMap` of property keys and values. + +[source,java] +---- +//Connect to the 'bunnymq' RabbitMQ service, setting properties +@Bean +public RabbitConnectionFactory rabbitFactory() { + Map properties = new HashMap(); + properties.put("requestedHeartbeat", 5); + properties.put("connectionTimeout", 10); + + RabbitConnectionFactoryConfig rabbitConfig = new RabbitConnectionFactoryConfig(properties); + return connectionFactory().rabbitConnectionFactory("bunnymq", rabbitConfig); +} +---- + +==== Relational database (DB2, MySQL, Oracle, PostgreSQL, SQL Server) + +To connect to a unique relational database service, create a service bean using `dataSource()`. The following example connects to the only relational database service bound to the application. + +[source,java] +---- +//Connect to the only available relational database service +@Bean +public DataSource dataSource() { + return connectionFactory().dataSource(); +} +---- + +To connect to a specific relational database service, you can use an overloaded variant of `dataSource()`. The following example connects specifically to the `my-own-personal-sql` MySQL service. + +[source,java] +---- +//Connect to the 'my-own-personal-sql' relational database service +@Bean +public DataSource dataSource() { + return connectionFactory().dataSource("my-own-personal-sql"); +} +---- + +To provide configuration for a relational database service, you can use an overloaded `dataSource()` variant. The following example connects to the `my-own-personal-sql` MySQL service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/relational/DataSourceConfig.html[`DataSourceConfig`], which is initialized with a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.PoolConfig.html[`PoolConfig`] that sets a `minPoolSize` of 5, a `maxPoolSize` of 30, and a `maxWaitTime` of 3000. + +[source,java] +---- +//Connect to the 'my-own-personal-sql' relational database service, supplying configuration +@Bean +public DataSource dataSource() { + PoolConfig poolConfig = new PoolConfig(5, 30, 3000); + DataSourceConfig dbConfig = new DataSourceConfig(poolConfig, null); + return connectionFactory().dataSource("my-own-personal-sql", dbConfig); +} +---- + +To set properties on a relational database service, you can use an overloaded variant of `dataSource()`. The following example connects to the `my-own-personal-sql` MySQL service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/relational/DataSourceConfig.html[`DataSourceConfig`]. The `DataSourceConfig` is initialized with a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.PoolConfig.html[`PoolConfig`] (which sets a `minPoolSize` of 5, a `maxPoolSize` of 30, and a `maxWaitTime` of 3000) and a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/relational/DataSourceConfig.ConnectionConfig.html[`ConnectionConfig`] (which sets the `useUnicode` and `characterEncoding` properties). + +[source,java] +---- +//Connect to the 'my-own-personal-sql' relational database service, setting properties +@Bean +public DataSource dataSource() { + PoolConfig poolConfig = new PoolConfig(5, 30, 3000); + ConnectionConfig connConfig = new ConnectionConfig("useUnicode=yes;characterEncoding=UTF-8"); + DataSourceConfig dbConfig = new DataSourceConfig(poolConfig, connConfig); + return connectionFactory().dataSource("my-own-personal-sql", dbConfig); +} +---- + +==== MongoDB + +Coming soon... + +==== Application monitoring (New Relic) + +Coming soon... + +==== Redis + +Coming soon... + +==== SMTP + +Coming soon... === Connecting to Generic Services From c688f76cb2219a82bb1534bc55de0c8feb1c629c Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Mon, 24 Aug 2015 16:27:43 -0700 Subject: [PATCH 2/6] updates to main SC Connectors doc; add 'Extending' section --- .../asciidoc/spring-cloud-connectors.adoc | 176 +++++++++++------- 1 file changed, 113 insertions(+), 63 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-connectors.adoc b/docs/src/main/asciidoc/spring-cloud-connectors.adoc index e3a5bcb..a60bb45 100644 --- a/docs/src/main/asciidoc/spring-cloud-connectors.adoc +++ b/docs/src/main/asciidoc/spring-cloud-connectors.adoc @@ -11,7 +11,7 @@ == Introduction -Spring Cloud Connectors provides a simple abstraction for JVM-based applications running on cloud platforms to discover bound services and deployment information at runtime, and provides support for registering discovered services as Spring beans. It is based on a plugin model so that the identical compiled application can be deployed locally or on any of multiple cloud platforms, and it supports custom service definitions through Java SPI. +Spring Cloud Connectors provides a simple abstraction for JVM-based applications running on cloud platforms to discover bound services and deployment information at runtime, and provides support for registering discovered services as Spring beans. It is based on a plugin model so that the identical compiled application can be deployed locally or on any of multiple cloud platforms, and it supports custom service definitions through Java Service Provider Interfaces (SPI). The Connectors project provides out-of-the-box support for discovering common services on Heroku and Cloud Foundry clouds. It also includes a properties-based connector that can supply configuration for development and testing. @@ -78,7 +78,7 @@ In Gradle, replacing `${VERSION}` with the desired version: ---- dependencies { - // to use Spring Cloud Connectors for development + // To use Spring Cloud Connectors for development compile 'org.springframework.cloud:spring-cloud-localconfig-connector:${VERSION}' // If you intend to deploy the app to Cloud Foundry @@ -92,7 +92,7 @@ dependencies { === Spring Applications -If you're writing a Spring application, include the <> dependency in addition to your cloud connector dependencies. +If you're writing a Spring application, include the <> dependency in addition to your cloud connector dependencies. In Maven: @@ -116,7 +116,7 @@ dependencies { } ---- -Then follow the instructions in the <> documentation on Spring configuration <<_the_java_configuration,using Java configuration>> or the <<_the_code_cloud_code_namespace,`` namespace>>. +Then follow the instructions in the <> documentation on Spring configuration <> or the <` namespace>>. === Non-Spring Applications @@ -132,7 +132,7 @@ This core library provides programmatic access to application and service inform [NOTE] ==== -If you are using Spring Cloud in a Spring application, you should consider <<_spring_cloud_spring_service_connector,automatically injecting Spring beans>> instead. +If you are using Spring Cloud in a Spring application, you should consider <<_spring_service_connector,automatically injecting Spring beans>> instead. ==== * Include the desired cloud connectors on the runtime classpath, <<_getting_started,as described in the main documentation>>. @@ -151,7 +151,7 @@ CloudFactory cloudFactory = new CloudFactory(); Cloud cloud = cloudFactory.getCloud(); ---- + -Note that you must have a `CloudConnector` suitable for your deployment environment on your classpath. For example, if you are deploying the application to Cloud Foundry, you must add the <<_spring_cloud_cloud_foundry_connector,Cloud Foundry Connector>> to your classpath. If no suitable `CloudConnector` is found, the `getCloud()` method will throw a `CloudException`. +Note that you must have a `CloudConnector` suitable for your deployment environment on your classpath. For example, if you are deploying the application to Cloud Foundry, you must add the <<_cloud_foundry_connector,Cloud Foundry Connector>> to your classpath. If no suitable `CloudConnector` is found, the `getCloud()` method will throw a `CloudException`. * Use the `Cloud` instance to access application and service information and to create service connectors. + @@ -175,65 +175,19 @@ DataSource ds = cloud.getServiceConnector(serviceId, DataSource.class, null /* default config */); ---- -=== Adding Cloud Connectors - -A cloud provider may extend Spring Cloud to make it work with a new cloud platform by adding a new `CloudConnector`. The connector is responsible for determining whether the application is running in the specific cloud, identifying application information (such as the name and instance ID of the particular running instance), and mapping bound services (such as URIs exposed in environment variables) as `ServiceInfo` objects. - -[TIP] -==== -See the <<_spring_cloud_cloud_foundry_connector,Cloud Foundry Connector>> and <<_spring_cloud_heroku_connector,Heroku Connector>> for examples. -==== - -Spring Cloud uses the Java SPI to discover available connectors. New cloud connectors should list the fully-qualified class name in the provider-configuration file at `META-INF/services/org.springframework.cloud.CloudConnector`. - -=== Adding Service Discovery - -To allow Spring Cloud to discover a new type of service (e.g. a `HelloWorldService`), create a `ServiceInfo` class containing the information necessary to connect to the service. If your service can be specified via a URI, extend `UriBasedServiceInfo` and provide the URI scheme in a call to the `super` constructor. - -The following class will expose information for a service available at `helloworld://username:password@host:port/Bonjour`. - -[source,java] ----- -public class HelloWorldServiceInfo extends UriBasedServiceInfo { - public static final String URI_SCHEME = "helloworld"; - - // Needed to support structured service definitions such as Cloud Foundry's - public HelloWorldServiceInfo(String id, String host, int port, String username, String password, String greeting) { - super(id, URI_SCHEME, host, port, username, password, greeting); - } - - // Needed to support URI-based service definitions such as Heroku's - public HelloWorldServiceInfo(String id, String uri) { - super(id, uri); - } -} ----- - -After creating the `ServiceInfo` class, you will need to create a `ServiceInfoCreator` for each cloud platform you want to support. You will probably want to extend the appropriate creator base class(es), such as `HerokuServiceInfoCreator`. This is often as simple as writing a method that (in the case of the `HelloWorldService`) instantiates a new `HelloWorldServiceInfo`. - -Register your `ServiceInfoCreator` classes in the appropriate provider-configuration file for your cloud's `ServiceInfoCreator` base class. - -=== Adding Service Connectors - -A service connector consumes a `ServiceInfo` discovered by the cloud connector and converts it into the appropriate service object, such as a `DataSource` in the case of a service definition that represents a SQL database. - -Service connectors may be tightly bound to the framework whose service objects they are creating. For example, some connectors in the <<_spring_cloud_spring_service_connector,Spring Service Connector>> create connection factories defined by Spring Data, for use in building Spring Data templates. - -To add new service connectors, implement `ServiceConnectorCreator` in your connector classes and list the fully-qualified class names in the provider-configuration file at `META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator`. - -== Spring Cloud Spring Service Connector +== Spring Service Connector See <>. -== Spring Cloud Cloud Foundry Connector +== Cloud Foundry Connector See <>. -== Spring Cloud Heroku Connector +== Heroku Connector See <>. -== Spring Cloud local-configuration Connector +== local-configuration Connector This connector provides the ability to configure Spring Cloud services locally for development or testing. **The current implementation reads from Java properties only.** @@ -293,17 +247,113 @@ Spring Cloud Core expects exactly one cloud connector to match the runtime envir If the connector is activated, it will iterate through all of the available properties for keys matching the pattern `spring.cloud.{serviceId}`. Each value is interpreted as a URI to a service, and the type of service is determined from the scheme. Every standard `UriBasedServiceInfo` is supported. -=== Supporting Additional Services - -Extend `LocalConfigServiceInfoCreator` with a creator for <<_adding_service_discovery,your service's `ServiceInfo` class>>. - -Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator`. - === Instance ID This connector creates a UUID for use as the instance ID, as Java does not provide any portable mechanism for reliably determining hostnames or PIDs. == Extending Spring Cloud Connectors -Coming soon... +Besides the built-in service and cloud support and the included Spring Service Connector, Spring Cloud Connectors can be extended to support additional cloud platforms, cloud services, or application frameworks. See below for details. + +=== Adding Cloud Connectors + +To allow Spring Cloud to detect a new cloud platform, add a cloud connector for the platform. A cloud connector determines whether the application is running in the specific cloud, identifies application information (such as the name and instance ID of the particular running instance), and maps bound services (such as URIs exposed in environment variables) as `ServiceInfo` objects. + +[TIP] +==== +See the https://github.com/spring-cloud/spring-cloud-connectors/tree/master/spring-cloud-cloudfoundry-connector[Cloud Foundry Connector] and https://github.com/spring-cloud/spring-cloud-connectors/tree/master/spring-cloud-heroku-connector[Heroku Connector] for examples. +==== + +Spring Cloud uses the https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html[Java SPI] to discover available connectors. + +To add new cloud connectors, your connector classes must implement the http://docs.spring.io/autorepo/docs/spring-cloud/current/api/index.html?org/springframework/cloud/CloudConnector.html[`CloudConnector`] interface. It includes three methods: + +* `boolean isInMatchingCloud()`: Determines whether the connector is operating in the cloud for which it provides support. ++ +Spring Cloud Connectors will call `isInMatchingCloud()` on each cloud connector included in an application. The first connector to respond `true` will be activated. +* `ApplicationInstanceInfo getApplicationInstanceInfo()`: Returns information about the running application instance. ++ +An `ApplicationInstanceInfo` must provide the instance id (`String`) and application id (`String`). Other properties can be added as needed to a `Map` and be returned via `getProperties()`. +* `List getServiceInfos()`: Returns a `ServiceInfo` object for each service bound to the application. ++ +`getServiceInfos()` can return an empty `List` if no services have been bound to the application. + +New cloud connectors should list the fully-qualified class name in the provider-configuration file at `META-INF/services/org.springframework.cloud.CloudConnector`. + +=== Adding Service Support + +To allow Spring Cloud to discover a new type of service, create a `ServiceInfo` class containing the information necessary to connect to the service. If your service can be specified via a URI, extend http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/UriBasedServiceInfo.html[`UriBasedServiceInfo`] and provide the URI scheme in a call to the `super` constructor. + +The following class will expose information for a `HelloWorldService` available at `helloworld://username:password@host:port/Bonjour`. + +[source,java] +---- +public class HelloWorldServiceInfo extends UriBasedServiceInfo { + public static final String URI_SCHEME = "helloworld"; + + // Needed to support structured service definitions such as Cloud Foundry's + public HelloWorldServiceInfo(String id, String host, int port, String username, String password, String greeting) { + super(id, URI_SCHEME, host, port, username, password, greeting); + } + + // Needed to support URI-based service definitions such as Heroku's + public HelloWorldServiceInfo(String id, String uri) { + super(id, uri); + } +} +---- + +After creating the `ServiceInfo` class, you will need to create a `ServiceInfoCreator` for each cloud platform you want to support. If you are adding service support for a cloud platform already supported by Spring Cloud Connectors, you will probably want to extend the appropriate creator base class(es). + +[cols="2,8", width="100%"] +|================================================================== +|**Cloud Foundry** | Extend `CloudFoundryServiceInfoCreator`. +|**Heroku** | Extend `HerokuServiceInfoCreator`. +|**local-configuration** | Extend `LocalConfigServiceInfoCreator`. +|================================================================== + +A `ServiceInfoCreator` often can be as simple as a method that instantiates a new `ServiceInfo`. + +[source,java] +---- +@Override +public HelloWorldServiceInfo createServiceInfo(String id, String uri) { + return new HelloWorldServiceInfo(id, uri); +} +---- + +Register your `ServiceInfoCreator` classes in the appropriate provider-configuration file for your cloud's `ServiceInfoCreator` base class. + +[cols="2,8", width="100%"] +|========================================================================================================================================================================= +|**Cloud Foundry** | Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator`. +|**Heroku** | Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.heroku.HerokuServiceInfoCreator`. +|**local-configuration** | Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator`. +|========================================================================================================================================================================= + +=== Adding Service Connectors + +To allow Spring Cloud to provide framework-specific service objects for supported cloud services, add a service connector for the framework. A service connector consumes a `ServiceInfo` discovered by the cloud connector and converts it into the appropriate service object (such as a `DataSource` in the case of a service definition that represents a SQL database). + +[TIP] +==== +Service connectors can be tightly bound to the framework whose service objects they are creating. For example, some connectors in the <<_spring_service_connector,Spring Service Connector>> create connection factories defined by Spring Data, for use in building Spring Data templates. +==== + +To add new service connectors, your connector classes must implement the http://docs.spring.io/autorepo/docs/spring-cloud/current/api/index.html?org/springframework/cloud/service/ServiceConnectorCreator.html[`ServiceConnectorCreator`] interface. It has three methods: + +* `SC create()`: Creates a service connection object from a given `ServiceInfo` and configuration. +* `Class getServiceConnectorType()`: Returns the type of the connection object that will be created. +* `Class getServiceInfoType()`: Returns the type of the `ServiceInfo` that the class will accept. + +//// +[source,java] +---- +public class Foo { + +} +---- +//// + +List the fully-qualified connector class names in the provider-configuration file at `META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator`. From a42be8337cb3d085ab2f26f377241041a9a8fe7e Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Mon, 24 Aug 2015 17:06:49 -0700 Subject: [PATCH 3/6] minor revisions to CF Connector doc --- .../spring-cloud-cloud-foundry-connector.adoc | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-cloud-foundry-connector.adoc b/docs/src/main/asciidoc/spring-cloud-cloud-foundry-connector.adoc index 000a909..39389c7 100644 --- a/docs/src/main/asciidoc/spring-cloud-cloud-foundry-connector.adoc +++ b/docs/src/main/asciidoc/spring-cloud-cloud-foundry-connector.adoc @@ -17,7 +17,7 @@ This connector checks for the presence of a `VCAP_APPLICATION` environment varia == Service Detection -The connector inspects Cloud Foundry’s `VCAP_SERVICES` environment variable to detect available services. This variable stores connection and identification information for service instances that are bound to Cloud Foundry applications. +The connector inspects Cloud Foundry's `VCAP_SERVICES` environment variable to detect available services. This variable stores connection and identification information for service instances that are bound to Cloud Foundry applications. Below is an example of a `VCAP_SERVICES` entry (edited for brevity). @@ -48,20 +48,20 @@ Below is an example of a `VCAP_SERVICES` entry (edited for brevity). For each service, the connector will consider the following fields: [cols="3,7", width="100%"] -|================================================================================================================================================================================ +|=========================================================================================================================================================================== |`tags` |Attributes or names of backing technologies behind the service. -|`label` |The service offering’s name (not to be confused with a service _instance’s_ name). +|`label` |The service offering’s name (not to be confused with a service _instance’s_ name). |`credentials.uri` |A URI pertaining to the service instance. |`credentials.uris` |URIs pertaining to the service instance. -|================================================================================================================================================================================ +|=========================================================================================================================================================================== If they are present, it will also consider the following fields: [cols="3,7", width="100%"] -|================================================================================================================================================================================ +|=========================================================================================================================================================================== |`credentials.jdbcUrl` |A JDBC connection string. |`credentials.${SCHEME}${URL}` |A service URL, where `${SCHEME}` is a URI scheme used by the service and `${URL}` is one of `Url`, `url`, `Uri`, and `uri`. -|================================================================================================================================================================================ +|=========================================================================================================================================================================== === Supported Services @@ -155,10 +155,3 @@ The connector will check for: * `uri` or `uris` using the scheme `sqlserver` * `jdbcUrl` field in `credentials` using the scheme `sqlserver` * `sqlserverUri`, `sqlserveruri`, `sqlserverUrl`, or `sqlserverurl` fields in `credentials` - -== Supporting New Service Types - -Extend `CloudFoundryServiceInfoCreator` with a creator for <<_adding_service_discovery,your service's `ServiceInfo` class>>. - -Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator`. - From f8e8861156e2c1a95da95b42d60e33ad942e1c7c Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Mon, 24 Aug 2015 17:08:03 -0700 Subject: [PATCH 4/6] remove section on new services (Heroku) --- docs/src/main/asciidoc/spring-cloud-heroku-connector.adoc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-heroku-connector.adoc b/docs/src/main/asciidoc/spring-cloud-heroku-connector.adoc index 5a7d1c2..a8185f6 100644 --- a/docs/src/main/asciidoc/spring-cloud-heroku-connector.adoc +++ b/docs/src/main/asciidoc/spring-cloud-heroku-connector.adoc @@ -72,12 +72,6 @@ The connector will check for: To add support for a new provider of a service already listed above, add the provider's environment prefix to the list in `getEnvPrefixes()` on the `ServiceInfoCreator` class. -== Supporting New Service Types - -Extend `HerokuServiceInfoCreator` with a creator for <<_adding_service_discovery,your service's `ServiceInfo` class>>. - -Add the fully-qualified class name for your creator to `META-INF/service/org.springframework.cloud.heroku.HerokuServiceInfoCreator`. - == Limitations Unlike Cloud Foundry, Heroku exposes very little application information that is retrievable from within a running instance (for example, there is no good way to find the name of the application). If your application requires access to such information, you must make the information available through environment variables. From 8b7d1dee218ae3f7da8125bf0ae83dd11bbecf6c Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Mon, 24 Aug 2015 18:02:40 -0700 Subject: [PATCH 5/6] complete Spring Service Connector doc --- ...spring-cloud-spring-service-connector.adoc | 373 +++++++++++++++++- 1 file changed, 352 insertions(+), 21 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc b/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc index 8de0fa2..880489b 100644 --- a/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc +++ b/docs/src/main/asciidoc/spring-cloud-spring-service-connector.adoc @@ -9,7 +9,7 @@ The Spring Service Connector is part of the <> project. -This library provides `ServiceConnectorCreator` implementations for `javax.sql.DataSource` and various link:http://projects.spring.io/spring-data/[Spring Data] connector factories. It also provides Java configuration and XML namespace support for connecting to cloud services, accessing cloud services, and accessing application properties. +This library provides `ServiceConnectorCreator` implementations for `javax.sql.DataSource` and various http://projects.spring.io/spring-data/[Spring Data] connector factories. It also provides Java configuration and XML namespace support for connecting to cloud services, accessing cloud services, and accessing application properties. == The Java Configuration @@ -17,14 +17,40 @@ Typical use of the Java configuration involves extending the `AbstractCloudConfi [TIP] ==== -If you are migrating an application that uses link:https://spring.io/blog/2011/11/04/using-cloud-foundry-services-with-spring-part-2-auto-reconfiguration/[auto-reconfiguration], you might first try the <<_scanning_for_services,service-scanning approach>> until you need more explicit control. +If you are migrating an application that uses https://spring.io/blog/2011/11/04/using-cloud-foundry-services-with-spring-part-2-auto-reconfiguration/[auto-reconfiguration], you might first try the <<_scanning_for_services,service-scanning approach>> until you need more explicit control. ==== -The Spring Service Connector Java configuration also offers a way to expose application and service properties in case you want lower-level access when creating your own service connectors (or for debugging purposes, etc.). +The Spring Service Connector Java configuration also offers a way to expose application and service properties in case you want lower-level access when creating your own service connectors (or for debugging purposes, etc.). === Creating Service Beans -The configuration shown in the following example creates a `DataSource` bean that connects to the only relational database service bound to the application (it will fail if there is no such unique service). It also creates a `MongoDbFactory` bean, which again connects to the only MongoDB service bound to the application. (For ways to connect to other services, see the link:http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/config/java/AbstractCloudConfig.html[Javadoc for `AbstractCloudConfig`].) +If you do not wish to extend `AbstractCloudConfig`, you can create your own http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/Cloud.html[`Cloud`] object as an alternative. + +[source,java] +---- +@Bean +public Cloud cloud() { + return new CloudFactory().getCloud(); +} +---- + +The following example creates a `DataSource` bean (without configuration) using the http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/Cloud.html#getSingletonServiceConnector(java.lang.Class,%20org.springframework.cloud.service.ServiceConnectorConfig)[`getSingletonServiceConnector()`] method on `Cloud`. + +[source,java] +---- +@Bean +@ConfigurationProperties(DataSourceProperties.PREFIX) +public DataSource dataSource() { + return cloud().getSingletonServiceConnector(DataSource.class, null); +} +---- + +[NOTE] +==== +Following examples presume a configuration class which extends `AbstractCloudConfig`. +==== + +The configuration shown in the following example creates a `DataSource` bean that connects to the only relational database service bound to the application (it will fail if there is no such unique service). It also creates a `MongoDbFactory` bean, which again connects to the only MongoDB service bound to the application. (For ways to connect to other services, see the http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/config/java/AbstractCloudConfig.ServiceConnectionFactory.html[Javadoc for `AbstractCloudConfig.ServiceConnectionFactory`].) [source,java] ---- @@ -33,12 +59,12 @@ class CloudConfig extends AbstractCloudConfig { public DataSource inventoryDataSource() { return connectionFactory().dataSource(); } - + @Bean public MongoDbFactory documentMongoDbFactory() { return connectionFactory().mongoDbFactory(); } - + // (More beans to obtain service connectors) } ---- @@ -51,9 +77,9 @@ You can specify a bean name by providing a value in the `@Bean` annotation. ---- Otherwise, bean names will match the method names. (This works in the same way as does Spring's Java configuration.) - + If you have more than one service of a type bound to the application or want explicit control over the services to which a bean is bound, you can pass the service names to methods such as `dataSource()` and `mongoDbFactory()`. - + [source,java] ---- class CloudConfig extends AbstractCloudConfig { @@ -70,12 +96,12 @@ class CloudConfig extends AbstractCloudConfig { // (More beans to obtain service connectors) } ---- - -Out of the box, the Spring Service Connector provides methods for connecting to a variety of services. For information on creating connections to supported services, see below. + +Out of the box, the Spring Service Connector provides methods for connecting to a variety of services. For information on using the Java configuration to create connections to supported services, see below. ==== RabbitMQ -To connect to a unique RabbitMQ service, create a service bean using `rabbitConnectionFactory()`. The following example connects to the only RabbitMQ service bound to the application. +To connect to a unique RabbitMQ service, you can create a service bean using `rabbitConnectionFactory()`. The following example connects to the only RabbitMQ service bound to the application. [source,java] ---- @@ -127,7 +153,7 @@ public RabbitConnectionFactory rabbitFactory() { ==== Relational database (DB2, MySQL, Oracle, PostgreSQL, SQL Server) -To connect to a unique relational database service, create a service bean using `dataSource()`. The following example connects to the only relational database service bound to the application. +To connect to a unique relational database service, you can create a service bean using `dataSource()`. The following example connects to the only relational database service bound to the application. [source,java] ---- @@ -178,23 +204,142 @@ public DataSource dataSource() { ==== MongoDB -Coming soon... +To connect to a unique MongoDB service, you can create a service bean using `mongoDbFactory()`. The following example connects to the only MongoDB service bound to the application. -==== Application monitoring (New Relic) +[source,java] +---- +//Connect to the only available MongoDB service +@Bean +public MongoDbFactory mongoFactory() { + return connectionFactory().mongoDbFactory(); +} +---- -Coming soon... +To provide configuration for a unique MongoDB service, you can use an overloaded `mongoDbFactory()` variant. The following example connects to the only MongoDB service bound to the application and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/document/MongoDbFactoryConfig.html[`MongoDbFactoryConfig`] that sets `writeConcern` to `NONE`, `connectionsPerHost` to 50, and `maxWaitTime` to 200. + +[source,java] +---- +//Connect to the only available MongoDB service, supplying configuration +@Bean +public MongoDbFactory mongoFactory() { + MongoDbFactoryConfig mongoConfig = new MongoDbFactoryConfig("NONE", 50, 200); + return connectionFactory().mongoDbFactory(mongoConfig); +} +---- + +To connect to a specific MongoDB service, you can use an overloaded variant of `mongoDbFactory()`. The following example connects specifically to the `mongo-service` MongoDB service. + +[source,java] +---- +//Connect to the 'mongo-service' MongoDB service +@Bean +public MongoDbFactory mongoFactory() { + return connectionFactory().mongoDbFactory("mongo-service"); +} +---- + +To connect to a specific MongoDB service and provide configuration, you can use an overloaded `mongoDbFactory()` variant. The following example connects to the `mongo-service` MongoDB service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/document/MongoDbFactoryConfig.html[`MongoDbFactoryConfig`] that sets `writeConcern` to `NONE`, `connectionsPerHost` to 50, and `maxWaitTime` to 200. + +[source,java] +---- +//Connect to the only available MongoDB service, supplying configuration +@Bean +public MongoDbFactory mongoFactory() { + MongoDbFactoryConfig mongoConfig = new MongoDbFactoryConfig("NONE", 50, 200); + return connectionFactory().mongoDbFactory("mongo-service", mongoConfig); +} +---- ==== Redis -Coming soon... +To connect to a unique Redis service, you can create a service bean using `redisConnectionFactory()`. The following example connects to the only Redis service bound to the application. -==== SMTP +[source,java] +---- +//Connect to the only available Redis service +@Bean +public RedisConnectionFactory redisFactory() { + return connectionFactory().redisConnectionFactory(); +} +---- -Coming soon... +To provide configuration for a unique Redis service, you can use an overloaded `redisConnectionFactory()` variant. The following example connects to the only Redis service bound to the application and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.html[`PooledServiceConnectorConfig`], which is initialized with a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.PoolConfig.html[`PoolConfig`] that sets a `minPoolSize` of 5, a `maxPoolSize` of 30, and a `maxWaitTime` of 3000. + +[source,java] +---- +//Connect to the only available Redis service, supplying configuration +@Bean +public RedisConnectionFactory redisFactory() { + PoolConfig poolConfig = new PoolConfig(5, 30, 3000); + PooledServiceConnectorConfig redisConfig = new PooledServiceConnectorConfig(poolConfig); + return connectionFactory().redisConnectionFactory(redisConfig); +} +---- + +To connect to a specific Redis service, you can use an overloaded variant of `redisConnectionFactory()`. The following example connects specifically to the `redis-service` Redis service. + +[source,java] +---- +//Connect to the 'redis-service' Redis service +@Bean +public RedisConnectionFactory redisFactory() { + return connectionFactory().redisConnectionFactory("redis-service"); +} +---- + +To connect to a specific Redis service and provide configuration, you can use an overloaded `redisConnectionFactory()` variant. The following example connects to the `redis-service` Redis service and supplies configuration using a http://docs.spring.io/autorepo/docs/spring-cloud/1.1.2.BUILD-SNAPSHOT/api/org/springframework/cloud/service/keyval/RedisConnectionFactoryConfig.html[`RedisConnectionFactoryConfig`], which is initialized with a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.PoolConfig.html[`PoolConfig`] that sets `writeConcern` to `NONE`, `connectionsPerHost` to 50, and `maxWaitTime` to 200. + +[source,java] +---- +//Connect to the 'redis-service' Redis service, supplying configuration +@Bean +public RedisConnectionFactory redisFactory() { + PoolConfig poolConfig = new PoolConfig(5, 30, 3000); + PooledServiceConnectorConfig redisConfig = new RedisConnectionFactoryConfig(poolConfig); + return connectionFactory().redisConnectionFactory("redis-service", redisConfig); +} +---- + +To connect to a specific Redis service and set properties on the service, you can use an overloaded variant of `redisConnectionFactory()`. The following example connects to the `redis-service` Redis service and sets the `timeout` property using a http://docs.spring.io/autorepo/docs/spring-cloud/1.1.2.BUILD-SNAPSHOT/api/org/springframework/cloud/service/keyval/RedisConnectionFactoryConfig.html[`RedisConnectionFactoryConfig`] initialized with a `HashMap` that contains the property key and value. + +[source,java] +---- +//Connect to the 'redis-service' Redis service, setting a property +@Bean +public RedisConnectionFactory redisFactory() { + Map properties = new HashMap(); + properties.put("timeout", 10); + RedisConnectionFactoryConfig redisConfig = new RedisConnectionFactoryConfig(properties); + return connectionFactory().redisConnectionFactory("redis-service", redisConfig); +} +---- + +To connect to a specific Redis service and provide configuration and property values for the service, you can use an overloaded variant of `redisConnectionFactory()`. The following example connects to the `redis-service` Redis service and uses a http://docs.spring.io/autorepo/docs/spring-cloud/1.1.2.BUILD-SNAPSHOT/api/org/springframework/cloud/service/keyval/RedisConnectionFactoryConfig.html[`RedisConnectionFactoryConfig`] initialized with a http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/PooledServiceConnectorConfig.PoolConfig.html[`PoolConfig`] (which sets `writeConcern` to `NONE`, `connectionsPerHost` to 50, and `maxWaitTime` to 200) and a `HashMap` (which contains a property key and value) to configure the service and set its `timeout` property. + +[source,java] +---- +//Connect to the 'redis-service' Redis service, providing configuration and setting a property +@Bean +public RedisConnectionFactory redisFactory() { + Map properties = new HashMap(); + properties.put("timeout", 10); + PoolConfig poolConfig = new PoolConfig(5, 30, 3000); + RedisConnectionFactoryConfig redisConfig = new RedisConnectionFactoryConfig(poolConfig, properties); + return connectionFactory().redisConnectionFactory("redis-service", redisConfig); +} +---- === Connecting to Generic Services -The Java configuration supports access to generic services (services which don't have a directly mapped method; this is typical for a newly-introduced service or when connecting to a private service in a private PaaS) through the `service()` method. It follows the same pattern as `dataSource()` etc., except that it allows you to supply the connector type as an additional parameter. +The Java configuration supports access to generic services (services which don't have a directly mapped method; this is typical for a newly-introduced service or when connecting to a private service in a private PaaS) through the `service()` method. It follows the same pattern as `dataSource()` etc., except that it allows you to supply the connector type as an additional parameter. The following example connects to a hypothetical service of type `Search`, called `search-service`. + +[source,java] +---- +@Bean +public Search search() { + return connectionFactory().service("search-service", Search.class); +} +---- === Scanning for Services @@ -207,7 +352,7 @@ You can scan for each bound service using the `@ServiceScan` annotation. (This i class CloudConfig { } ---- - + In the above example, the configuration will create one bean of the appropriate type (such as a `DataSource` in the case of a relational database service). Each bean will have an `id` matching the corresponding service name. You can inject such beans using autowiring. @@ -284,6 +429,188 @@ Other namespace elements which create service connectors include: ---- +For information on using the `` namespace to create connections to services with built-in support in the Spring Service Connector, see below. + +==== RabbitMQ + +To connect to a RabbitMQ service, you can use the `` element. The following example connects to the only RabbitMQ service bound to the application. + +[source,xml] +---- + + +---- + +To connect to a specific RabbitMQ service, you can use the `service-name` attribute. The following example connects specifically to the `bunnymq` RabbitMQ service. + +[source,xml] +---- + + +---- + +To specify an id for the RabbitMQ connection bean, you can use the `id` attribute. The following example connects specifically to the `bunnymq` RabbitMQ service with a bean given the id `rabbitmq`. + +[source,xml] +---- + + +---- + +To set properties on a RabbitMQ service, you can use the `` nested element. The following example connects specifically to the `bunnymq` RabbitMQ service with a bean given the id `rabbitmq` and uses the `` element to set the size of the channel cache to 200. + +[source,xml] +---- + + + + +---- + +To set connection properties on a RabbitMQ service, you can use the `` nested element. The following example connects specifically to the `bunnymq` RabbitMQ service with a bean given the id `rabbitmq`. It uses the `` element to set the size of the channel cache to 200, and it uses the `` element to set a heartbeat timeout of 5 seconds and a connection timeout of 10 milliseconds. + +[source,xml] +---- + + + + + + + + +---- + +==== Relational database (DB2, MySQL, Oracle, PostgreSQL, SQL Server) + +To connect to a relational database service, you can use the `` element. The following example connects to the only relational database service bound to the application. + +[source,xml] +---- + + +---- + +To connect to a specific relational database service, you can use the `service-name` attribute. The following example connects specifically to the `my-own-personal-sql` MySQL service. + +[source,xml] +---- + + +---- + +To specify an id for the relational database connection bean, you can use the `id` attribute. The following example connects specifically to the `my-own-personal-sql` MySQL service with a bean given the id `mysql`. + +[source,xml] +---- + + +---- + +To set connection properties on a relational database service, you can use the `` nested element. The following example connects specifically to the `my-own-personal-sql` MySQL service with a bean given the id `mysql` and uses the `` element to set the `useUnicode` and `characterEncoding` properties. + +[source,xml] +---- + + + + +---- + +To configure pool settings on a relational database service, you can use the `` nested element. The following example connects specifically to the `my-own-personal-sql` MySQL service with a bean given the id `mysql`. It uses the `` element to set a `pool-size` of 5–30 and a `max-wait-time` of 3000 milliseconds. + +[source,xml] +---- + + + + +---- + +==== MongoDB + +To connect to a MongoDB service, you can use the `` element. The following example connects to the only MongoDB service bound to the application. + +[source,xml] +---- + + +---- + +To connect to a specific MongoDB service, you can use the `service-name` attribute. The following example connects specifically to the `mongo-service` MongoDB service. + +[source,xml] +---- + + +---- + +To specify an id for the MongoDB connection bean, you can use the `id` attribute. The following example connects specifically to the `mongo-service` MongoDB service with a bean given the id `mongo`. + +[source,xml] +---- + + +---- + +To set properties on a MongoDB service, you can use the `` nested element. The following example connects specifically to the `mongo-service` MongoDB service with a bean given the id `mongo` and uses the `` element to allow 50 connections per host. + +[source,xml] +---- + + + + +---- + +==== Redis + +To connect to a Redis service, you can use the `` element. The following example connects to the only Redis service bound to the application. + +[source,xml] +---- + + +---- + +To connect to a specific Redis service, you can use the `service-name` attribute. The following example connects specifically to the `redis-service` Redis service. + +[source,xml] +---- + + +---- + +To specify an id for the Redis connection bean, you can use the `id` attribute. The following example connects specifically to the `redis-service` Redis service with a bean given the id `redis`. + +[source,xml] +---- + + +---- + +To set connection properties on a Redis service, you can use the `` nested element. The following example connects specifically to the `redis-service` Redis service with a bean given the id `redis` and uses the `` element to set a `timeout` of `10`. + +[source,xml] +---- + + + + + + +---- + +To configure pool settings on a Redis service, you can use the `` nested element. The following example connects specifically to the `redis-service` Redis service with a bean given the id `redis`. It uses the `` element to set a `pool-size` of 5–30 and a `max-wait-time` of 3000 milliseconds. + +[source,xml] +---- + + + + +---- + === Connecting to Generic Services Spring Service Connector also supports a generic `` namespace for connecting to a service with no directly-mapped element (this is typical for a newly-introduced service or when connecting to a private service in a private PaaS). You must specify either the `connector-type` attribute (for locating a unique service by type) or the `service-name` attribute. @@ -299,5 +626,9 @@ Besides these elements (which create only one bean per element), Spring Service === Accessing Service Properties -Lastly, Spring Service Connector provides a `` element, which exposes properties for the application and for services. +Spring Service Connector also provides a `` element, which exposes properties for the application and for services. +[source,xml] +---- + +---- From 1ebeec22046c13e8763eaede18b7eea051ff9047 Mon Sep 17 00:00:00 2001 From: Ben Klein Date: Mon, 24 Aug 2015 21:01:56 -0700 Subject: [PATCH 6/6] remove (commented-out) dummy code --- docs/src/main/asciidoc/spring-cloud-connectors.adoc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-connectors.adoc b/docs/src/main/asciidoc/spring-cloud-connectors.adoc index a60bb45..27878cf 100644 --- a/docs/src/main/asciidoc/spring-cloud-connectors.adoc +++ b/docs/src/main/asciidoc/spring-cloud-connectors.adoc @@ -346,14 +346,5 @@ To add new service connectors, your connector classes must implement the http:// * `Class getServiceConnectorType()`: Returns the type of the connection object that will be created. * `Class getServiceInfoType()`: Returns the type of the `ServiceInfo` that the class will accept. -//// -[source,java] ----- -public class Foo { - -} ----- -//// - List the fully-qualified connector class names in the provider-configuration file at `META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator`.