Overhaul Markdown documentation. Spring connector still needs rework.

link check

rewrite main README

link check

rewrite core doc

rephrase heading for clarity

weird GFM indentation in code blocks

info on adding ServiceInfos

update docs for Heroku and CF connectors

improve docs for local connector

tweak description of service connectors

edits as discussed in #54

reword Spring registration
This commit is contained in:
Christopher Smith
2014-07-16 17:33:15 -05:00
parent bf826f8a58
commit 1b675fa5e7
5 changed files with 310 additions and 165 deletions

157
README.md
View File

@@ -1,69 +1,116 @@
Spring-cloud offers a simple way for JVM apps in cloud to access services and discover their own information during runtime with special support for Spring apps. It offers an extensibility mechanism to make it work on multiple clouds and a variety of cloud services. Through the abstraction of cloud connector, you can make it work with multiple clouds (we include two examples: Cloud Foundry and Heroku) without touching the spring-cloud project itself. Through the service connector abstraction, you can make it work with a variety of services (such as all the new ones on Cloud Foundry marketplace), again, without touching the spring-cloud project itself.
Spring Cloud 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 multiple clouds, and it supports custom service
definitions through Java SPI.
Spring Cloud provides out-of-the-box support for discovering common services on Heroku and
Cloud Foundry clouds as well as a properties-based configuration for development and testing.
The core concepts used in this project are:
1. **Cloud Connector**: An interface that a cloud provider can implement to allow the rest of the library work with a Platform As a Service (PaaS) offering.
2. **Service Connector**: An object, such as `javax.sql.DataSource`, that represent a connection to a service.
3. **Service information**: Information about the underlying service such as host, port, and credentials.
4. **Application information**: Information about application and instance in which these libraries are embedded.
- [**Cloud connector**](./spring-cloud-core/src/main/java/org/springframework/cloud/CloudConnector.java):
An interface specific to a cloud platform that identifies the presence of the platform and
discovers any services bound to the application deployment.
- **Service connector**: An object, such as a `javax.sql.DataSource`, that represents a runtime
connection to a service.
- [**Service information**](./spring-cloud-core/src/main/java/org/springframework/cloud/service/ServiceInfo.java):
Information about the underlying service such as host, port, and credentials.
- [**Application information**](./spring-cloud-core/src/main/java/org/springframework/cloud/app/ApplicationInstanceInfo.java):
Information about the application and the particular running instance.
The project comprises of four subprojects:
The project contains three major submodules:
1. **[core](spring-cloud-core)**: Core library that is cloud agnostic and Spring agnostic. Provides entry point for application developers that choose to programmatically access cloud services and application information. It also provides an extension mechanism to contribute cloud connectors and service connector creators.
2. **[spring-service-connector](spring-cloud-spring-service-connector)**: Library that provides service connectors creators for javax.sql.DataSource and various connection factories spring-data projects.
3. **[cloudfoundry-connector](spring-cloud-cloudfoundry-connector)**: Cloud connector for [Cloud Foundry](http://www.cloudfoundry.com).
4. **[heroku-connector](spring-cloud-heroku-connector)**: Cloud connector for [Heroku](http://www.heroku.com).
- **[core](spring-cloud-core)**: The core library, cloud- and Spring-agnostic, that provides
a programmatic entry point for developers who prefer to access cloud services and application
information manually. It also provides basic service definitions for several common services
(databases, message queues) and an SPI-based extension mechanism to contribute
cloud and service connectors.
- **[spring-service-connector](spring-cloud-spring-service-connector)**: A Spring Library that
exposes application and cloud information and discovered services as Spring beans of the
appropriate type. For example, SQL services will be exposed as `javax.sql.DataSource`s with
optional connection pooling.
- Cloud connectors:
- **[cloudfoundry-connector](spring-cloud-cloudfoundry-connector)**: Connector for [Cloud Foundry](http://cloudfoundry.org).
- **[heroku-connector](spring-cloud-heroku-connector)**: Connector for [Heroku](https://www.heroku.com).
- **[localconfig-connector](spring-cloud-localconfig-connector)**: Properties-based connector for
manually providing configuration information for development or testing. Allows the use of the
same Spring Cloud configuration wiring in all stages of application deployment.
Getting Started
===============
##Getting Started
The following assumes that you are using Maven.
The following examples are written for Maven; simply include the appropriate dependencies for
your build system.
Spring apps
-----------
###Including cloud connectors
Add the [`spring-service-connector`](spring-cloud-spring-service-connector) and one or more cloud connectors dependencies (it is okay to add more that one cloud connectors):
Include the connector for each cloud platform you want to be discoverable. Including multiple
connectors is perfectly fine; each connector will determine whether it should be active in a
particular environment.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app on Cloud Foundry, add the following -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app on Heroku, add the following -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-heroku-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
````xml
<!-- to use Spring Cloud for development -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-localconfig-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
Then follow instructions on [how you use the Java config and `<cloud>` namespace](spring-cloud-spring-service-connector). You can also follow the [instructions](spring-cloud-core) on using the core API directly.
<!-- If you intend to deploy the app to Cloud Foundry -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
Non-spring apps
<!-- If you intend to deploy the app to Heroku -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-heroku-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
````
###Spring applications
Add the [`spring-service-connector`](spring-cloud-spring-service-connector) in
addition to your cloud connectors:
````xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<!-- to use Spring Cloud for development -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-localconfig-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app to Cloud Foundry -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app to Heroku -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-heroku-connector</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
````
Then follow the instructions on [Spring configuration using Java configuration or
the `<cloud>` namespace](spring-cloud-spring-service-connector).
###Non-Spring applications
---------------
Add the [`core`](core) and one or more cloud connectors dependencies (it is okay to add more that one cloud connectors):
The [`spring-cloud-core`](core) dependency is included by each cloud connector,
so simply include the connectors for the platforms you want.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-core</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app on CloudFoundry, add the following -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<!-- If you intend to deploy the app on Heroku, add the following -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-heroku-connector</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
Then follow the [instructions](spring-cloud-core) on using spring-cloud API.
Then follow the [instructions](spring-cloud-core) on using the Spring Cloud API.

View File

@@ -1,23 +1,27 @@
Cloud Foundry connector for spring-cloud
========================================
#Spring Cloud Cloud Foundry connector
Provides Cloud Foundry connector with support for Mysql, Postgres, RabbitMQ, MongoDB, and Redis services.
This connector will discover services bound to an application running in Cloud Foundry.
It currently knows about:
Supporting additional services
------------------------------
The cloudfoundry-connector offers extending support for additional services
through the same [`ServiceLoader`](http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html)
mechanism used in the [core](../spring-cloud-core) project.
It allows extending to new services without modifying the [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector)
itself. All you need to do is:
- PostgreSQL
- MySQL
- Oracle
- Redis
- MongoDB
- RabbitMQ
- SMTP gateway
- application monitoring (New Relic)
1. Create a new project declaring dependency of [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector).
2. Add one implementation of [`CloudFoundryServiceInfoCreator`](src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryServiceInfoCreator.java)
for each service type you wish to extend.
Along the way, you will, of course, add an implementation of [`ServiceInfo`](../core/main/java/org/springframework/cloud/service/ServiceInfo.java)
(consider extending [`BaseServiceInfo`](../core/main/java/org/springframework/cloud/service/BaseServiceInfo.java)),
attach an [`@ServiceLabel`](../core/main/java/org/springframework/cloud/service/ServiceLabel.java) annotation,
and mark appropriate properties with [`@ServiceProperty`]((../core/main/java/org/springframework/cloud/service/ServiceProperty.java)) annotation.
3. Add a file on classpath
`META-INF/services/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator`
and add all your implementations of `CloudFoundryServiceInfoCreator`.
Since Cloud Foundry enumerates each service in a consistent format, Spring Cloud does
not care which service provider is providing it.
##Supporting new service types
Extend [`CloudFoundryServiceInfoCreator`]((src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryServiceInfoCreator.java))
with a creator for [your service's `ServiceInfo` class](../spring-cloud-core/#adding-service-discovery).
Add the fully-qualified class name for your creator to
````
META-INF/service/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator
````

View File

@@ -1,71 +1,131 @@
Spring Cloud Core Library
=========================
#Spring Cloud Core
The core library to let cloud applications access application information and services.
While Spring applications is one of the main target for this library, it may be used in
non-Spring projects as well. In fact, **this library doesn't even depend on Spring**.
This core library provides programmatic access to application and service information. This library
has no Spring dependencies and may be used in non-Spring applications.
This library requires Java 6,
This library requires Java 6 or newer.
This library is cloud-agnostic. Through connectors, it supports multiple clouds
(with Cloud Foundry and Heroku as the example clouds).
This library is cloud-agnostic. Using Java SPI, it supports pluggable cloud and service
connectors; support for Cloud Foundry and Heroku is available out-of-the-box, in addition to
locally-provided configuration for development and testing.
This library also supports an extension to create services connectors of user-desired types.
##Connecting to a cloud
Usage pattern: Application Developers
=====================================
> **Note:** If you are using Spring Cloud in a Spring application, you should consider
[automatically injecting Spring beans](../spring-cloud-spring-service-connector) instead.
> **Note:** If you are using spring-cloud in a Spring application, you should consider using the
[Java config](../spring-cloud-spring-service-connector#the-java-config) or the
[XML namespace support](../spring-cloud-spring-service-connector#the-cloud-namespace) instead.
* Include the desired cloud connectors on the runtime classpath
[as described in the main documentation](../#including-cloud-connectors).
* Create a [`CloudFactory`](src/main/java/org/springframework/cloud/CloudFactory.java) instance.
Creation of a `CloudFactory` instance is a bit expensive, so caching such an instance is recommended.
If you are using a dependency injection frameworks such as Spring, creating a bean for `CloudFactory`
will achieve the caching effect.
Creation of a `CloudFactory` instance is a bit expensive, so using a singleton instance is recommended.
If you are using a dependency injection framework such as Spring, create a bean for the `CloudFactory`.
```java
CloudFactory cloudFactory = new CloudFactory();
CloudFactory cloudFactory = new CloudFactory();
```
* Obtain a suitable [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) for the environment
* Obtain the [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) object for the environment
in which the application is running.
```java
Cloud cloud = cloudFactory.getCloud();
Cloud cloud = cloudFactory.getCloud();
```
Note that you must have a `CloudConnector` implementation suitable
for the environment in which the application is being deployed in your classpath. For example, if you are
deploying the application in Cloud Foundry, you must add [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector)
in your classpath. If no suitable `CloudConnctor` is found, the `getCloud()` method will throw a `CloudException`.
* Use the `Cloud` instance to get access to application info, service infos, and create service
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 [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector)
to your classpath. If no suitable `CloudConnctor` is found, the `getCloud()` method will throw a [
`CloudException`](../spring-cloud-core/src/main/java/org/springframework/cloud/CloudException.java).
* Use the `Cloud` instance to access application and service information and to create service
connectors.
```java
// ServiceInfo has all the information necessary to connect to the underlying service
cloud.getServiceInfos();
// ServiceInfo has all the information necessary to connect to the underlying service
List<ServiceInfo> serviceInfos = cloud.getServiceInfos();
```
```java
// Alternatively, let the cloud create a service connector for you
DataSource ds = cloud.getServiceConnector("inventory-db", DataSource.class, null /* default config */);
// find the `ServiceInfo` definitions suitable for connecting to a particular service type
List<ServiceInfo> databaseInfos = cloud.getServiceInfos(DataSource.class);
````
```java
// Alternately, let Spring Cloud create a service connector for you
String serviceId = "inventory-db";
DataSource ds = cloud.getServiceConnector(serviceId, DataSource.class, null /* default config */);
```
Usage pattern: Cloud and Service Providers
==========================================
A cloud provider may extends the functionality in two ways:
##Adding cloud connectors
1. Add new [`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)s to make
spring-cloud related libraries work with a new cloud.
See [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector)
or [heroku-connector](../spring-cloud-heroku-connector) for an example.
This is done declaratively by adding connector classes to:
```
META-INF/services/org.springframework.cloud.CloudConnector
```
2. Add new [`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)s
to allow creation of service connector objects.
See [spring-service-connector](../spring-cloud-spring-service-connector) for an example.
This is done declaratively by adding creator classes to:
```
META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator
```
A cloud provider may extend Spring Cloud by adding a new
[`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)
to make Spring Cloud work with a new cloud platform. The connector is responsible for
telling 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.
See the [Cloud Foundry](../spring-cloud-cloudfoundry-connector)
and [Heroku](../spring-cloud-heroku-connector) connectors 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 (`HelloWorldService`),
create a `ServiceInfo` class containing the information necessary to connect to your
service. If your service can be specified via a URI, extend `UriBasedServiceInfo`
and provide the URI scheme in a call to the `super` constructor.
This class will expose information for a service available at
````
helloworld://username:password@host:port/Bonjour
````
````java
public class HelloWorldServiceInfo extends UriBasedServiceInfo {
public static final String URI_SCHEME = "helloworld";
// needed to support structured service definitions like Cloud Foundry
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 like Heroku
public HelloWorldServiceInfo(String id, String uri) {
super(id, uri);
}
}
````
Then 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 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` for a service definition
representing 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 service connector](../spring-cloud-spring-service-connector) create connection
factories defined by Spring Data, for use in building Spring Data templates.
To add new service connectors, implement
[`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)
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
````

View File

@@ -1,23 +1,43 @@
Heroku connector for spring-cloud
=======================================
#Spring Cloud Heroku connector
Provides Heroku connector with support for Postgres (Mysql, RabbitMQ, MongoDB, and Redis services
coming soon; PR requests welcome).
This connector will discover services bound to an application running in Heroku. It
currently knows about:
Supporting additional services
------------------------------
Please see the documentation for [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector), since the same
mechanism applies to any cloud connector.
- PostgreSQL (Heroku)
- MySQL (ClearDB)
- Redis (RedisToGo, Redis Cloud, RedisGreen, openredis)
- MongoDB (MongoLab, MongoHQ, MongoSoup)
- RabbitMQ (CloudAMQP)
Limitations
-----------
Unlike CloudFoundry, Heroku exposes very little information about the app that is retrievable from
within a running app. For example, there is no good way to know the name of the application.
Therefore, if an app desires such info, it needs to make that available through environment variables.
Pull requests for adding additional services are welcome.
##Supporting additional providers for existing service types
To add support for discovering a new provider for 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`](src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java)
with a creator for [your service's `ServiceInfo` class](../spring-cloud-core/#adding-service-discovery).
Add the fully-qualified class name for your creator to
````
META-INF/service/org.springframework.cloud.heroku.HerokuServiceInfoCreator
````
##Limitations
Unlike CloudFoundry, Heroku exposes very little information about the app that is retrievable
from within a running instance. For example, there is no good way to find the name of the
application. Therefore, if an app desires such info, it needs to make it available through
environment variables.
To have sensible app name available through [`ApplicationInstanceInfo`](../core/src/main/java/org/springframework/cloud/app/ApplicationInstanceInfo.java),
set the `SPRING_CLOUD_APP_NAME` environment variable
To have sensible app name available through [`ApplicationInstanceInfo`](../core/src/main/java/org/springframework/cloud/app/ApplicationInstanceInfo.java)
(and associated properties), set the `SPRING_CLOUD_APP_NAME `variable
heroku config:add SPRING_CLOUD_APP_NAME=myappname --app myappname
If this env variable is not set, the app name will be set to `<unknown>`.

View File

@@ -1,16 +1,21 @@
Local-configuration connector for Spring Cloud
=======================================
#Spring Cloud local-configuration connector
Provides the ability to configure Spring Cloud services locally for development or testing.
The current implementation reads from Java properties only; in order to prevent dependencies
on the Spring Framework, the placeholder functionality is unavailable in the connector.
Pull requests for also inspecting environment variables are welcome.
This connector provides the ability to configure Spring Cloud services locally for development
or testing. The current implementation reads from Java properties only; in order to prevent
dependencies on the Spring Framework, the placeholder functionality is unavailable in the
connector. Pull requests for also inspecting environment variables are welcome.
##Quick start
Quick start
-----------
Since service URIs contain passwords and should not be stored in code, this connector does not
attempt to read properties out of the classpath. You can provide a filename with service definitions
by setting the `spring.cloud.propertiesFile` property or by passing in an open `InputStream`:
by setting the `spring.cloud.propertiesFile` system property:
````
java -Dspring.cloud.propertiesFile=/path/to/spring-cloud.properties -jar my-app.jar
````
or by passing in an open `InputStream`:
````java
InputStream propertyStream = new FileInputStream("/path/to/spring-cloud.properties");
@@ -26,10 +31,12 @@ spring.cloud.appId: myApp
spring.cloud.database: mysql://user:pass@host:1234/dbname
````
Service type is determined by the URI scheme.
Service type is determined by the URI scheme. The connector will activate if it finds a property
(in the system properties, supplied properties, or the file provided in `spring.cloud.propertiesFile`)
named `spring.cloud.appId`.
##Property sources
Property sources
----------------
This connector first attempts to read the system properties generally and a system property named
`spring.cloud.propertiesFile` specifically. If the system properties are not readable
(the security manager denies `checkPropertiesAccess`), then they will be treated as empty.
@@ -45,7 +52,7 @@ still read the stream, but the properties will have no effect on the connector
service configuration. Calling this method multiple times will load the supplied
streams onto the same `Properties` object, overwriting duplicates.
###Property order
###Property precedence
To provide the maximum configuration flexibility, the connector will scan the available
property sources in this order:
@@ -56,25 +63,32 @@ property sources in this order:
The last definition of a specific service ID wins. The connector will log a message at
`WARN` if you override a service ID.
Activating the connector
------------------------
The Spring Cloud core expects exactly one cloud connector to return `true` for
`isInMatchingCloud()`. This connector identifies the "local cloud" by the presence of
a property named `spring.cloud.appId`, which will be used in the `ApplicationInstanceInfo`.
##Activating the connector
The Spring Cloud core expects exactly one cloud connector match the runtime environment.
This connector identifies the "local cloud" by the presence of a property named
`spring.cloud.appId`, which will be used in the `ApplicationInstanceInfo`.
##Service definitions
Service definitions
-------------------
If the connector is activated, it will iterate through all the available properties
for keys matching the pattern `spring.cloud.{serviceId}`. Each value is interpreted as a URI
to the services, and the type of service is determined from the scheme. All of the standard
`UriBasedServiceInfo`s are supported.
Supporting additional services
------------------------------
Please see the documentation for [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector), since the same
mechanism applies to any cloud connector.
##Supporting additional services
Extend [`LocalConfigServiceInfoCreator`](src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java)
with a creator for [your service's `ServiceInfo` class](../spring-cloud-core/#adding-service-discovery).
Add the fully-qualified class name for your creator to
````
META-INF/service/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator
````
##Instance ID
Instance ID
-----------
This connector will create a UUID for use as the instance ID, as Java does not provide
any portable mechanism for reliably determining hostnames or PIDs.