SGF-305 - Finished migration to Asciidoctor.

Upgraded Asciidoctor plugin to 1.5 and re-enabled Docbook plugin for PDF generation. Removed obsolete repository declarations. Use Spring Data Build shared resources to use the CSS file from it. Configure Docbook reference plugin to use Asciidoctor generated sources. Override expandPlaceholders to avoid replacement of variables in source files. Tweaked docs ZIP setup to include Asciidoctor generated HTML and Docbook generated PDF version.
(cherry picked from commit 639293adfe)

Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2014-09-03 17:18:36 -07:00
parent ae82ddffab
commit 3beed647eb
21 changed files with 167 additions and 502 deletions

View File

@@ -3,17 +3,22 @@ buildscript {
maven { url 'http://repo.spring.io/plugins-release' }
}
dependencies {
classpath('org.asciidoctor:asciidoctor-gradle-plugin:0.7.0')
classpath('org.asciidoctor:asciidoctor-java-integration:0.1.4.preview.1')
classpath 'org.springframework.build.gradle:bundlor-plugin:0.1.2'
classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0'
classpath('org.asciidoctor:asciidoctor-gradle-plugin:1.5.0')
classpath('org.asciidoctor:asciidoctorj:1.5.0')
classpath 'org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE'
}
}
configurations {
sharedResources
}
description = 'Spring Data GemFire'
group = 'org.springframework.data'
repositories {
maven { url "http://dist.gemstone.com.s3.amazonaws.com/maven/release"}
maven { url "http://repo.spring.io/libs-snapshot" }
maven { url "http://repo.spring.io/plugins-release"}
}
@@ -23,8 +28,9 @@ apply plugin: "java"
apply plugin: 'eclipse'
apply plugin: 'idea'
apply from: "$rootDir/maven.gradle"
//apply plugin: 'bundlor'
apply plugin: 'asciidoctor'
apply plugin: 'docbook-reference'
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
apply plugin: 'bundlor'
if (project.hasProperty('platformVersion')) {
apply plugin: 'spring-io'
@@ -46,31 +52,6 @@ tasks.withType(Test).all {
systemProperties['org.springframework.data.gemfire.test.GemfireTestRunner.nomock'] = System.getProperty('org.springframework.data.gemfire.test.GemfireTestRunner.nomock')
}
asciidoctor {
sourceDocumentName = new File("$sourceDir/index.adoc")
outputDir = new File("$buildDir/reference/htmlsingle")
options = [
eruby: 'erubis',
attributes: [
linkcss: 'true',
copycss : 'spring.css',
icons : 'font',
'source-highlighter': 'prettify',
sectanchors : '',
toc: '',
toclevels: '4',
idprefix: '',
idseparator: '-',
doctype: 'book',
numbered: '',
version: project.version,
baseDir: "$sourceDir",
stylesheet: "spring.css",
referenceDir: "$sourceDir/reference"
]
]
}
// Common dependencies
dependencies {
// Spring Framework
@@ -115,6 +96,8 @@ dependencies {
testRuntime "log4j:log4j:$log4jVersion"
testCompile "org.apache.derby:derbyLocale_zh_TW:10.9.1.0"
testRuntime "org.slf4j:slf4j-log4j12:$slf4jVersion"
sharedResources "org.springframework.data.build:spring-data-build-resources:$springDataBuildVersion@zip"
}
sourceCompatibility = 1.6
@@ -135,7 +118,7 @@ javadoc {
groups = [
'Spring GemFire' : ['org.springframework.data.gemfire*'],
]
links = [
"http://static.springframework.org/spring/docs/3.1.x/javadoc-api",
"http://download.oracle.com/javase/6/docs/api",
@@ -144,10 +127,10 @@ javadoc {
"http://logging.apache.org/log4j/docs/api/",
"http://atinject.googlecode.com/svn/trunk/javadoc/"
]
exclude "org/springframework/data/gemfire/config/**"
}
title = "${rootProject.description} ${version} API"
}
@@ -163,6 +146,38 @@ jar {
}
}
// Reference documentation
reference {
// Avoid copy with expansions
expandPlaceholders = '';
}
referencePdf {
dependsOn = [ 'asciidoctor' ]
sourceDir = asciidoctor.outputDir
}
asciidoctor {
dependsOn = [ 'extractSharedResources' ]
backends = [ 'html5', 'docbook' ]
options = [
doctype: 'book',
eruby: 'erubis',
attributes: [
linkcss: true,
copycss : "$buildDir/shared-resources/asciidoc/spring.css",
icons : 'font',
'source-highlighter': 'prettify',
sectanchors : true,
toclevels: '3',
sectids: false,
numbered: true,
version: project.version,
stylesheet: "spring.css",
]
]
}
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = 'sources'
@@ -178,6 +193,7 @@ task docsZip(type: Zip) {
group = 'Distribution'
classifier = 'docs'
description = "Builds -${classifier} archive containing api and reference for deployment"
dependsOn = [ 'javadoc', 'asciidoctor', 'referencePdf' ]
from('docs/src/info') {
include 'changelog.txt'
@@ -190,9 +206,12 @@ task docsZip(type: Zip) {
from (asciidoctor.outputDir) {
include "index.html"
include "spring.css"
into 'reference/htmlsingle'
into 'reference/html'
}
from (referencePdf.outputDir) {
into 'reference'
}
}
task schemaZip(type: Zip) {
@@ -201,7 +220,7 @@ task schemaZip(type: Zip) {
description = "Builds -${classifier} archive containing all XSDs for deployment"
def Properties schemas = new Properties();
sourceSets.main.resources.find {
it.path.endsWith('META-INF' + File.separator + 'spring.schemas')
}?.withInputStream { schemas.load(it) }
@@ -214,7 +233,7 @@ task schemaZip(type: Zip) {
it.path.replace('\\', '/').endsWith(schemas.get(key))
}
assert xsdFile != null
into (shortName) {
from xsdFile.path
rename { String fileName -> alias }
@@ -237,7 +256,7 @@ task distZip(type: Zip, dependsOn: [jar, docsZip, schemaZip, sourcesJar, javadoc
include 'notice.txt'
expand(copyright: new Date().format('yyyy'), version: project.version)
}
from('samples/') {
into 'samples'
exclude '**/build/**'
@@ -246,7 +265,7 @@ task distZip(type: Zip, dependsOn: [jar, docsZip, schemaZip, sourcesJar, javadoc
exclude '**/vf*.*'
exclude '**/vf*.txt'
}
from(zipTree(docsZip.archivePath)) {
into "docs"
}
@@ -285,6 +304,15 @@ task wrapper(type: Wrapper) {
}
}
task extractSharedResources(type: Copy) {
from { // use of closure defers evaluation until execution time
configurations.sharedResources.collect { zipTree(it) }
}
into "$buildDir/shared-resources"
}
assemble.dependsOn = ['jar', 'sourcesJar']
defaultTasks 'build'

View File

@@ -11,4 +11,5 @@ slf4jVersion=1.7.6
spring.range="[4.0.0, 5.0.0)"
springVersion=4.0.6.RELEASE
springDataCommonsVersion=1.9.0.BUILD-SNAPSHOT
springDataBuildVersion=1.5.0.BUILD-SNAPSHOT
version=1.5.0.BUILD-SNAPSHOT

View File

@@ -1,16 +1,16 @@
[[appendix-schema]]
[appendix]
= Spring Data GemFire Schema
:resourcesDir: ../../main/resources
Spring Data GemFire Core Schema (gfe)
== Spring Data GemFire Core Schema (gfe)
[source,xml]
----
include::{resourcesDir}/org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd[]
----
Spring Data GemFire Data Access Schema (gfe-data)
== Spring Data GemFire Data Access Schema (gfe-data)
[source,xml]
----

View File

@@ -1,40 +1,38 @@
= Spring Data GemFire Reference Guide
Costin Leau , David Turanski , John Blum , Oliver Gierke
:baseDir: .
:revnumber: {version}
:revdate: {localdate}
:toc:
:toc-placement!:
:spring-data-commons-docs: https://raw.githubusercontent.com/spring-projects/spring-data-commons/master/src/main/asciidoc
{version}
(C) 2011-2014 The original authors.
(C) 2011-2014 The original authors
NOTE: As of the 1.2.0 release, this project, formerly known as Spring GemFire, has been renamed to Spring Data GemFire to reflect that it is now a component of the Spring Data project.
NOTE: _Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically._
NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
toc::[]
[[spring-gemfire-reference]]
include::{baseDir}/preface.adoc[]
:numbered:
:leveloffset: 0
[[introduction]]
= Introduction
:leveloffset: 2
:leveloffset: +1
include::{baseDir}/introduction/introduction.adoc[]
include::{baseDir}/introduction/requirements.adoc[]
include::{baseDir}/introduction/new-features.adoc[]
:leveloffset: -1
:leveloffset: 0
[[reference]]
= Reference Guide
:leveloffset: 1
:leveloffset: +1
include::{baseDir}/reference/introduction.adoc[]
include::{baseDir}/reference/bootstrap.adoc[]
:leveloffset: 1
include::{baseDir}/reference/data.adoc[]
include::{baseDir}/reference/serialization.adoc[]
include::{baseDir}/reference/mapping.adoc[]
@@ -42,22 +40,19 @@ include::{baseDir}/reference/repositories.adoc[]
include::{baseDir}/reference/function-annotations.adoc[]
include::{baseDir}/reference/gemfire-bootstrap.adoc[]
include::{baseDir}/reference/samples.adoc[]
:leveloffset: -1
:leveloffset: 0
[[resources]]
= Other Resources
In addition to this reference documentation, there are a number of other resources that may help you learn how to use GemFire and Spring framework. These additional, third-party resources are enumerated in this section.
:leveloffset: 1
:leveloffset: +1
include::{baseDir}/links.adoc[]
:leveloffset: -1
:leveloffset: 0
[[appendices]]
= Appendices
:numbered!:
:leveloffset: 1
[appendix]
:leveloffset: +1
include::{baseDir}/appendix/appendix-schema.adoc[]

View File

@@ -1,7 +1,7 @@
[[new-features]]
= New Features
NOTE: As of the 1.2.0 release, this project, formerly known as Spring GemFire, has been renamed to Spring Data GemFire
NOTE: As of the 1.2.0 release, this project, formerly known as Spring GemFire, has been renamed to Spring Data GemFire
to reflect that it is now a component of the http://www.springsource.org/spring-data[Spring Data] project.
[[new-in-1-2-0]]
@@ -81,3 +81,4 @@ for more details.
* Enables Spring Data GemFire to be fully built and ran on JDK 7 and JDK 8 (Note, however, GemFire has not yet been fully tested and supported on JDK 8;
See http://pubs.vmware.com/vfabric53/topic/com.vmware.vfabric.gemfire.7.0/getting_started/system_requirements/supported_configurations.html[GemFire User Guide]
for additional details.

View File

@@ -6,3 +6,4 @@
* https://www.vmware.com/support/pubs/vfabric-gemfire.html[Pivotal GemFire Documentation]
* http://communities.vmware.com/community/vmtn/appplatform/vfabric_gemfire[Pivotal GemFire Community Home Page]
* http://forum.spring.io/forum/spring-projects/data/gemfire[Spring Data GemFire Forum<]

View File

@@ -1,4 +1,3 @@
[preface]
= Preface
Spring Data GemFire focuses on integrating the Spring Framework's powerful, non-invasive programming model and concepts with Pivotal GemFire, simplifying configuration, development and providing high-level abstractions. This document assumes the reader already has a basic familiarity with the Spring Framework and Pivotal GemFire concepts and APIs.

View File

@@ -1,6 +1,5 @@
[[bootstrap]]
= Bootstrapping GemFire through the Spring Container
:referenceDir: .
Spring Data GemFire provides full configuration and initialization of the GemFire data grid through Spring's IoC container and provides several classes that simplify the configuration of GemFire components including Caches, Regions, WAN Gateways, Persistence Backup, and other Distributed System components to support a variety of scenarios with minimal effort.
@@ -28,9 +27,8 @@ To use the Spring Data GemFire namespace, simply declare it in your Spring XML c
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlxsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:<!--1-->
gfe="http://www.springframework.org/schema/gemfire"<!--2-->
xmlxsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gfe="http://www.springframework.org/schema/gemfire"<!--1--><!--2-->
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd"> <!--3-->
@@ -53,8 +51,7 @@ It is possible to change the default namespace, for example from `beans` to `gfe
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns= <!--1-->
"http://www.springframework.org/schema/gemfire"
<beans xmlns="http://www.springframework.org/schema/gemfire" <!--1-->
xmlxsi="http://www.w3.org/2001/XMLSchema-instance"
<!--2-->
xmlns:beans="http://www.springframework.org/schema/beans"
@@ -74,12 +71,12 @@ It is possible to change the default namespace, for example from `beans` to `gfe
<4> Bean declaration using the `gfe` namespace. Notice the lack of prefix (as the default namespace is used).
====
:leveloffset: 2
include::{referenceDir}/cache.adoc[]
include::{referenceDir}/data-access.adoc[]
include::{referenceDir}/region.adoc[]
:leveloffset: +1
include::cache.adoc[]
include::data-access.adoc[]
include::region.adoc[]
:leveloffset: -1
:leveloffset: 1
[[bootstrap:indicies]]
== Creating an Index
@@ -87,14 +84,15 @@ GemFire allows creation on indexes (or indices) to improve the performance of (c
[source,xml]
----
<gfe:index id="myIndex" expression="someField" from="/someRegion"/>
<gfe:index id="myIndex" expression="someField" from="/someRegion" />
----
Before creating an index, Spring Data GemFire will verify whether one with the same name already exists. If it does, it will compare the properties and if they don't match, will remove the old one to create a new one. If the properties match, Spring Data GemFire will simply return the index (in case it does not exist it will simply create one). To prevent the update of the index, even if the properties do not match, set the property `override` to false.
Note that index declaration are not bound to a region but rather are top-level elements (just like `gfe:cache`). This allows one to declare any number of indecies on any region whether they are just created or already exist - an improvement versus the GemFire `cache.xml`. By default the index relies on the default cache declaration but one can customize it accordingly or use a pool (if need be) - see the namespace schema for the full set of options.
:leveloffset: 2
include::{referenceDir}/diskstore.adoc[]
include::{referenceDir}/function.adoc[]
include::{referenceDir}/gateway.adoc[]
:leveloffset: +1
include::diskstore.adoc[]
include::function.adoc[]
include::gateway.adoc[]
:leveloffset: -1

View File

@@ -44,9 +44,9 @@ In addition to referencing an external configuration file one can specify GemFir
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<gfe:cache properties-ref="props"/>
<util:properties id="props" location="file:/vfabric/gemfire/gemfire.properties"/>
</beans>
----
@@ -63,7 +63,7 @@ For advanced cache configuration, the `cache` element provides a number of confi
<!--1-->
<gfe:cache
copy-on-read="true"
critical-heap-percentage="70"
critical-heap-percentage="70"
eviction-heap-percentage="60"
lock-lease="120"
lock-timeout="60"
@@ -75,18 +75,18 @@ For advanced cache configuration, the `cache` element provides a number of confi
message-sync-interval="1"
search-timeout="300"
close="false"
lazy-init="true"
>
lazy-init="true">
<gfe:transaction-listener ref="myTransactionListener"/><!--2-->
<gfe:transaction-writer> <!--3-->
<bean class="org.springframework.data.gemfire.example.TransactionListener"/>
</gfe:transaction-writer>
<gfe:dynamic-region-factory/> <!--4-->
<gfe:jndi-binding jndi-name="myDataSource" type="ManagedDataSource"/> <!--5-->
</gfe:cache>
----
<1> Various cache options are supported by attributes. For further information regarding anything shown in this example, please consult the GemFire product http://www.vmware.com/support/pubs/vfabric-gemfire.html[documentation]
@@ -121,7 +121,7 @@ In Spring Data GemFire 1.1 dedicated support for configuring a http://www.vmware
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
@@ -132,7 +132,7 @@ In Spring Data GemFire 1.1 dedicated support for configuring a http://www.vmware
<gfe:cache-server id="advanced-config" auto-startup="true"
bind-address="localhost" port="${gfe.port.6}" host-name-for-clients="localhost"
load-poll-interval="2000" max-connections="22" max-threads="16"
max-message-count="1000" max-time-between-pings="30000"
max-message-count="1000" max-time-between-pings="30000"
groups="test-server">
<gfe:subscription-config eviction-type="ENTRY" capacity="1000" disk-store="file://${java.io.tmpdir}"/>
@@ -157,7 +157,7 @@ Another configuration addition in Spring Data GemFire 1.1 is the dedicated suppo
[source,xml]
----
<beans>
<gfe:client-cache />
<gfe:client-cache />
</beans>
----

View File

@@ -53,19 +53,18 @@ In particular, note how the above implementation of the `EventDelegate` interfac
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd">
<gfe:client-cache pool-name="client"/>
<gfe:pool id="client" subscription-enabled="true">
<gfe:server host="localhost" port="40404"/>
</gfe:pool>
<gfe:cq-listener-container>
<!-- default handle method -->
<gfe:listener ref="listener" query="SELECT * from /region"/ >
<gfe:listener ref="another-listener" query="SELECT * from /another-region" name="my-query" method="handleQuery"/>
</gfe:cq-listener-container>
<bean id="listener" class="gemfireexample.DefaultMessageDelegate"/>
<bean id="another-listener" class="gemfireexample.DefaultMessageDelegate"/>
...

View File

@@ -17,7 +17,7 @@ For many applications, A basic connection to a GemFire grid, using default value
The datasource tag is syntactically similar to `<gfe:pool>`. It may be configured with one or more locator or server tags to connect to an existing data grid. Additionally, all attributes available to configure a pool are supported. This configuration will automatically create ClientRegion beans for each region defined on members connected to the locator, so they may be seamlessly referenced by Spring Data mapping annotations, GemfireTemplate, and wired into application classes.
Of course, you can explicitly configure client regions. For example, if you want to cache data in local memory:
Of course, you can explicitly configure client regions. For example, if you want to cache data in local memory:
[source,xml]
----

View File

@@ -1,6 +1,5 @@
[[apis]]
= Working with the GemFire APIs
:referenceDir:
Once the GemFire Cache and Regions have been configured they can be injected and used inside application objects. This chapter describes the integration with Spring's Transaction Management functionality and `DaoException` hierarchy. It also covers support for dependency injection of GemFire managed objects.
@@ -82,10 +81,10 @@ NOTE: The example above can be simplified even more by eliminating the `cache-re
Currently, GemFire supports optimistic transactions with *read committed* isolation. Furthermore, to guarantee this isolation, developers should avoid making *in-place* changes that manually modify values present in the Cache. To prevent this from happening, the transaction manager configures the Cache to use *copy on read* semantics, meaning a clone of the actual value is created, each time a read is performed. This behavior can be disabled if needed through the `copyOnRead` property. For more information on the semantics of the underlying GemFire transaction manager, see the GemFire https://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/cache/CacheTransactionManager.html[documentation].
:leveloffset: 2
include::{referenceDir}/cq-container.adoc[]
:leveloffset: +1
include::cq-container.adoc[]
:leveloffset: -1
:leveloffset: 1
[[apis:declarable]]
== Wiring `Declarable` components
@@ -152,7 +151,7 @@ public class DBLoader extends WiringDeclarableSupport implements CacheLoader {
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" ... />
@@ -182,14 +181,14 @@ In the scenario above, as no parameter was specified, a bean with the id/name `c
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" ... />
<!-- template bean definition -->
<!-- template bean definition -->
<bean id="template-bean" abstract="true" p:dataSource-ref="dataSource"/>
</beans>
----
@@ -205,7 +204,7 @@ For example, the hypothetical `DBLoader` declaration above can be injected with
[source,java]
----
public class DBLoader extends WiringDeclarableSupport implements CacheLoader {
// use annotations to 'mark' the needed dependencies
// use annotations to 'mark' the needed dependencies
@javax.inject.Inject
private DataSource dataSource;
@@ -228,14 +227,14 @@ public class DBLoader extends WiringDeclarableSupport implements CacheLoader {
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- enable annotation processing -->
<!-- enable annotation processing -->
<context:annotation-config/>
</beans>
----

View File

@@ -7,7 +7,7 @@ NOTE: Prior to Release 1.2.0, `disk-store` was a child element of `*-region`. If
[source,xml]
----
<gfe:disk-store id="diskStore1" queue-size="50" auto-compact="true"
<gfe:disk-store id="diskStore1" queue-size="50" auto-compact="true"
max-oplog-size="10" time-interval="9999">
<gfe:disk-dir location="/gemfire/store1/" max-size="20"/>
<gfe:disk-dir location="/gemfire/store2/" max-size="20"/>

View File

@@ -42,17 +42,17 @@ The following example illustrates how annotations are used to expose a POJO as a
[source,java]
----
@Component
@Component
public class MyFunctions {
@GemfireFunction
public String function1(String s1, @RegionData Map<?,?> data, int i2) { ... }
@GemfireFunction("myFunction", HA=true, optimizedForWrite=true, batchSize=100)
public List<String> function2(String s1, @RegionData Map<?,?> data, int i2, @Filter Set<?> keys) { ... }
public String function1(String s1, @RegionData Map<?,?> data, int i2) { ... }
@GemfireFunction("myFunction", HA=true, optimizedForWrite=true, batchSize=100)
public List<String> function2(String s1, @RegionData Map<?,?> data, int i2, @Filter Set<?> keys) { ... }
@GemfireFunction(hasResult=true)
public void functionWithContext(FunctionContext functionContext) { ... }
}
public void functionWithContext(FunctionContext functionContext) { ... }
}
----
Note that the class itself must be registered as a Spring bean. Here the `@Component` annotation is used, but you may register the bean by any method provided by Spring (e.g. XML configuration or Java configuration class). This allows the Spring container to create an instance of this class and wrap it in a https://github.com/SpringSource/spring-gemfire/blob/master/src/main/java/org/springframework/data/gemfire/function/PojoFunctionWrapper.java[PojoFunctionWrapper](PFW). Spring creates one PFW instance for each method annotated with `@GemfireFunction`. Each will all share the same target object instance to invoke the corresponding method.

View File

@@ -11,7 +11,7 @@ As of Release 1.3.0, Spring Data GemFire provides <<function-annotations,annotat
<ref bean="function2"/>
</gfe:function>
</gfe:function-service>
<bean id="function2" class="com.company.example.Function2"/>
----

View File

@@ -10,7 +10,7 @@ GemFire 7.0 introduces new APIs for WAN configuration. While the original APIs p
[source,xml]
----
<gfe:partitioned-region id="region-inner-gateway-sender" >
<gfe:gateway-sender
<gfe:gateway-sender
remote-distributed-system-id="1">
<gfe:event-filter>
<bean class="org.springframework.data.gemfire.example.SomeEventFilter"/>
@@ -21,15 +21,15 @@ GemFire 7.0 introduces new APIs for WAN configuration. While the original APIs p
</gfe:gateway-sender>
<gfe:gateway-sender-ref bean="gateway-sender"/>
</gfe:partitioned-region>
<gfe:async-event-queue id="async-event-queue" batch-size="10" persistent="true" disk-store-ref="diskstore"
<gfe:async-event-queue id="async-event-queue" batch-size="10" persistent="true" disk-store-ref="diskstore"
maximum-queue-memory="50">
<gfe:async-event-listener>
<bean class="org.springframework.data.gemfire.example.SomeAsyncEventListener"/>
</gfe:async-event-listener>
</gfe:async-event-queue>
<gfe:gateway-sender id="gateway-sender" remote-distributed-system-id="2">
<gfe:event-filter>
<ref bean="event-filter"/>
@@ -40,7 +40,7 @@ GemFire 7.0 introduces new APIs for WAN configuration. While the original APIs p
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
</gfe:transport-filter>
</gfe:gateway-sender>
<bean id="event-filter" class="org.springframework.data.gemfire.example.AnotherEventFilter"/>
<bean id="transport-filter" class="org.springframework.data.gemfire.example.AnotherTransportFilter"/>
----
@@ -49,7 +49,7 @@ On the other end of a `GatewaySender` is a corresponding `GatewayReceiver` to re
[source,xml]
----
<gfe:gateway-receiver id="gateway-receiver"
<gfe:gateway-receiver id="gateway-receiver"
start-port="12345" end-port="23456" bind-address="192.168.0.1">
<gfe:transport-filter>
<bean class="org.springframework.data.gemfire.example.SomeTransportFilter"/>
@@ -72,7 +72,7 @@ Please refer to the GemFire product document for a detailed explanation of all t
<gfe:gateway-listener>
<bean class="com.company.example.MyGatewayListener"/>
</gfe:gateway-listener>
<gfe:gateway-queue maximum-queue-memory="5" batch-size="3"
<gfe:gateway-queue maximum-queue-memory="5" batch-size="3"
batch-time-interval="10" />
</gfe:gateway>

View File

@@ -30,7 +30,7 @@ As of Spring Data GemFire 1.4, such an *Initializer* is already conveniently pro
<string>classpath:application-context.xml</string>
</parameter>
</initializer>
</cache>
</cache>
----
The `SpringContextBootstrappingInitializer` class follows similar conventions as Spring's ContextLoaderListener class for bootstrapping a Spring context inside a Web Application, where application context configuration files are specified with the `contextConfigLocations` Servlet Context Parameter. In addition, the `SpringContextBootstrappingInitializer` class can also be used with a `basePackages` parameter to specify a comma-separated list of base package containing the appropriately annotated application components that the Spring container will search using component scanning and create Spring beans for:
@@ -48,7 +48,7 @@ The `SpringContextBootstrappingInitializer` class follows similar conventions as
<string>org.mycompany.myapp.services,org.mycompany.myapp.dao,...</string>
</parameter>
</initializer>
</cache>
</cache>
----
Then, with a properly configured and constructed `CLASSPATH` along with the `cache.xml` file shown above specified as a command-line option when starting a GemFire Server in Gfsh, the command-line would be:
@@ -57,7 +57,7 @@ Then, with a properly configured and constructed `CLASSPATH` along with the `cac
----
gfsh>start server --name=Server1 --log-level=config ...
--classpath="/path/to/spring-data-gemfire-1.4.0.jar:/path/to/application/classes.jar"
--cache-xml-file="/path/to/gemfire/cache.xml"
--cache-xml-file="/path/to/gemfire/cache.xml"
----
The `application-context.xml` can be any valid Spring context configuration meta-data including all the SDG namespace elements. The only limitation with this approach is that the GemFire Cache cannot be configured using the Spring Data GemFire namespace. In other words, none of the `<gfe:cache/>` element attributes, such as `cache-xml-location`, `properties-ref`, `critical-heap-percentage`, `pdx-serializer-ref`, `lock-lease`, etc can be specified. If used, these attributes will be ignored. The main reason for this is that GemFire itself has already created an initialized the Cache before the *Initializer* gets invoked. As such, the Cache will already exist and since it is a "Singleton", it cannot be re-initialized or have any of it's configuration augmented.
@@ -78,7 +78,7 @@ public static final class UserDataSourceCacheLoader extends LazyWiringDeclarable
private DataSource userDataSource;
...
}
}
----
As implied by the CacheLoader example above, you might necessarily (although, rare) have defined both a Region and CacheListener component in GemFire `cache.xml`. The CacheLoader may need access to an application DAO, or perhaps Spring application context defined JDBC Data Source for loading "Users" into a GemFire Cache `REPLICATE` Region on start. Of course, one should be careful in mixing the different life-cycles of GemFire and the Spring Container together in this manner as not all use cases and scenarios are supported. The GemFire `cache.xml` configuration would be similar to the following (which comes from SDG's test suite):
@@ -105,6 +105,6 @@ As implied by the CacheLoader example above, you might necessarily (although, ra
<string>org.springframework.data.gemfire.support.sample</string>
</parameter>
</initializer>
</cache>
</cache>
----

View File

@@ -40,8 +40,8 @@ public class Admin extends User {
@Region("/Users/Guest")
public class Guest extends User {
...
}
}
----
Be sure to use the full-path of the GemFire Region, as defined in Spring Data GemFire XML namespace configuration meta-data, as specified in the `id` or `name` attributes of the `<*-region>` bean definition.
@@ -60,7 +60,7 @@ public interface PersonRepository extends GemfireRepository<Person, String> {
@Region("Customers")
public interface CustomerRepository extends GemfireRepository<Person, String> {
...
}
}
----
[[mapping.pdx-serializer]]
@@ -78,7 +78,7 @@ public class Person {
// …
}
}
}
----
====

View File

@@ -9,7 +9,7 @@ GemFire implements the following types of regions:
* *Partioned* - Data is partitioned into buckets among cache members that define the region. This provides high read and write performance and is suitable for very large data sets that are too big for a single node.
* *Local* - Data only exists on the local node.
* *Client* - Technically a client region is a local region that acts as a proxy to a replicated or partitioned region hosted on cache servers. It may hold data created or fetched locally. Alternately, it can be empty. Local updates are synchronized to the cache server. Also, a client region may subscribe to events in order to stay synchronized with changes originating from remote processes that access the same region.
For more information about the various region types and their capabilities as well as configuration options, please refer to the GemFire Developer's http://pubs.vmware.com/vfabricNoSuite/index.jsp?topic=/com.vmware.vfabric.gemfire.7.0/developing/book_intro.html[Guide] and community http://communities.vmware.com/community/vmtn/appplatform/vfabric_gemfire[site].
[[bootstrap:region:lookup]]
@@ -45,19 +45,19 @@ The `lookup-region` provides a simple way of retrieving existing, pre-configured
[[bootstrap:region:overview]]
== Configuring Regions
Spring Data GemFire provides comprehensive support for configuring any type of GemFire Region via the following elements:
Spring Data GemFire provides comprehensive support for configuring any type of GemFire Region via the following elements:
* Local Region `<local-region>`
* Replicated Region `<replicated-region>`
* Partitioned Region `<partitioned-region>`
* Client Region `<client-region>`
* Client Region `<client-region>`
For a comprehensive description of http://pubs.vmware.com/vfabricNoSuite/topic/com.vmware.vfabric.gemfire.7.0/developing/region_options/region_types.html[Region types] please consult the GemFire product documentation.
[[bootstrap:region:common:attributes]]
=== Common Region Attributes
The following table(s) list attributes available for various region types:
The following table(s) list attributes available for various region types:
[cols="1,2,2", options="header"]
.Common Region Attributes
@@ -65,7 +65,7 @@ The following table(s) list attributes available for various region types:
| Name
| Values
| Description
| cache-ref
| *GemFire Cache bean name*
| The name of the bean defining the GemFire Cache (by default 'gemfireCache').
@@ -79,7 +79,7 @@ The following table(s) list attributes available for various region types:
| Determines whether members perform checks to provide consistent handling for concurrent or out-of-order updates to distributed Regions.
| data-policy
| *See GemFire's http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/cache/DataPolicy.html[Data Policy]*
| *See GemFire's http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/cache/DataPolicy.html[Data Policy]*
| The Region's Data Policy. Note, not all Data Policies are supported for every Region type.
| destroy
@@ -146,7 +146,7 @@ The following table(s) list attributes available for various region types:
[[bootstrap:region:common:cache-listener]]
=== Cache Listeners
Cache Listeners are registered with a region to handle region events such as entries being created, updated, destroyed, etc. A Cache Listener can be any bean that implements the http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/cache/CacheListener.html[`CacheListener`] interface. A region may have multiple listeners, declared using the `cache-listener` element enclosed in a `*-region` element. In the example below, there are two `CacheListener`s declared. The first references a top-level named Spring bean; the second is an anonymous inner bean definition.
Cache Listeners are registered with a region to handle region events such as entries being created, updated, destroyed, etc. A Cache Listener can be any bean that implements the http://www.vmware.com/support/developer/vfabric-gemfire/700-api/com/gemstone/gemfire/cache/CacheListener.html[`CacheListener`] interface. A region may have multiple listeners, declared using the `cache-listener` element enclosed in a `*-region` element. In the example below, there are two `CacheListener`s declared. The first references a top-level named Spring bean; the second is an anonymous inner bean definition.
[source,xml]
----
@@ -162,7 +162,7 @@ Cache Listeners are registered with a region to handle region events such as ent
</gfe:replicated-region>
----
The following example uses an alternate form of the `cache-listener` element with a `ref` attribute. This allows for more concise configuration for a single cache listener. Note that the namespace only allows a single `cache-listener` element so either the style above or below must be used.
The following example uses an alternate form of the `cache-listener` element with a `ref` attribute. This allows for more concise configuration for a single cache listener. Note that the namespace only allows a single `cache-listener` element so either the style above or below must be used.
WARNING: Using `ref` and a nested declaration in a `cache-listener`, or similar element, is illegal. The two options are mutually exclusive and using both on the same element will result in an exception.
@@ -179,7 +179,7 @@ WARNING: Using `ref` and a nested declaration in a `cache-listener`, or similar
----
.Bean Reference Conventions
[NOTE]
[NOTE]
====
The `cache-listener` element is an example of a common pattern used in the namespace anywhere GemFire provides a callback interface to be implemented in order to invoke custom code in response to cache or region events. Using Spring's IoC container, the implementation is a standard Spring bean. In order to simplify the configuration, the schema allows a single occurrence of the `cache-listener` element, but it may contain nested bean references and inner bean definitions in any combination if multiple instances are permitted. The convention is to use the singular form (i.e., `cache-listener` vs `cache-listeners`) reflecting that the most common scenario will in fact be a single instance. We have already seen examples of this pattern in the <<null,advanced cache>> configuration example.
====
@@ -192,7 +192,7 @@ Similar to `cache-listener`, the namespace provides `cache-loader` and `cache-wr
[[bootstrap:region:common:subregions]]
=== Subregions
In Release 1.2.0, Spring Data GemFire added support for subregions, allowing regions to be arranged in a hierarchical relationship. For example, GemFire allows for a */Customer/Address* region and a different */Employee/Address* region. Additionally, a subregion may have it's own subregions and its own configuration. A subregion does not inherit attributes from the parent region. Regions types may be mixed and matched subject to GemFire constraints. A subregion is naturally declared as a child element of a region. The subregion's name attribute is the simple name. The above example might be configured as: [source,xml]
In Release 1.2.0, Spring Data GemFire added support for subregions, allowing regions to be arranged in a hierarchical relationship. For example, GemFire allows for a */Customer/Address* region and a different */Employee/Address* region. Additionally, a subregion may have it's own subregions and its own configuration. A subregion does not inherit attributes from the parent region. Regions types may be mixed and matched subject to GemFire constraints. A subregion is naturally declared as a child element of a region. The subregion's name attribute is the simple name. The above example might be configured as: [source,nonxml]
----
<beans>
@@ -375,7 +375,7 @@ For a detailed description of eviction policies, see the GemFire documentation (
== Data Expiration
GemFire allows you to control how long entries exist in the cache. Eviction is driven by elapsed time, as opposed to eviction which is driven by memory usage. Once an entry expires it may no longer be accessed from the cache. GemFire supports the following expiration types:
* *Time to live (TTL)* - The amount of time, in seconds, the object may remain in the cache after the last creation or update. For entries, the counter is set to zero for create and put operations. Region counters are reset when the region is created and when an entry has its counter reset.
* *Idle timeout* - The amount of time, in seconds, the object may remain in the cache after the last access. The idle timeout counter for an object is reset any time its TTL counter is reset. In addition, an entrys idle timeout counter is reset any time the entry is accessed through a get operation or a netSearch . The idle timeout counter for a region is reset whenever the idle timeout is reset for one of its entries.

View File

@@ -17,9 +17,9 @@ To bootstrap Spring Data repositories you use the `<repositories />` element fro
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/gemfire
http://www.springframework.org/schema/data/gemfire
http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd>
<gfe-data:repositories base-package="com.acme.repository" />

View File

@@ -1,356 +0,0 @@
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
audio, canvas, video { display: inline-block; }
audio:not([controls]) { display: none; height: 0; }
[hidden] { display: none; }
html { background: #fff; color: #000; font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; }
body { margin: 0; }
a:focus { outline: thin dotted; }
a:active, a:hover { outline: 0; }
h1 { font-size: 2em; margin: 0.67em 0; }
abbr[title] { border-bottom: 1px dotted; }
b, strong { font-weight: bold; }
dfn { font-style: italic; }
hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
mark { background: #ff0; color: #000; }
code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
pre { white-space: pre-wrap; }
q { quotes: "\201C" "\201D" "\2018" "\2019"; }
small { font-size: 80%; }
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }
img { border: 0; }
svg:not(:root) { overflow: hidden; }
figure { margin: 0; }
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
legend { border: 0; padding: 0; }
button, input, select, textarea { font-family: inherit; font-size: 100%; margin: 0; }
button, input { line-height: normal; }
button, select { text-transform: none; }
button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer; }
button[disabled], html input[disabled] { cursor: default; }
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; }
input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
textarea { overflow: auto; vertical-align: top; }
table { border-collapse: collapse; border-spacing: 0; }
*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
html, body { font-size: 100%; }
body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
a:hover { cursor: pointer; }
a:focus { outline: none; }
img, object, embed { max-width: 100%; height: auto; }
object, embed { height: 100%; }
img { -ms-interpolation-mode: bicubic; }
#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
.left { float: left !important; }
.right { float: right !important; }
.text-left { text-align: left !important; }
.text-right { text-align: right !important; }
.text-center { text-align: center !important; }
.text-justify { text-align: justify !important; }
.hide { display: none; }
.antialiased, body { -webkit-font-smoothing: antialiased; }
img { display: inline-block; vertical-align: middle; }
textarea { height: auto; min-height: 50px; }
select { width: 100%; }
p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; }
.subheader, #content #toctitle, .admonitionblock td.content > .title, .exampleblock > .title, .imageblock > .title, .videoblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, .sidebarblock > .title, .tableblock > .title, .verseblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title, .tableblock > caption { line-height: 1.4; color: #7a2518; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
a { color: #060; text-decoration: underline; line-height: inherit; }
a:hover, a:focus { color: #040; }
a img { border: none; }
p { font-family: inherit; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; text-rendering: optimizeLegibility; }
p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Georgia, "URW Bookman L", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; color: #ba3925; text-rendering: optimizeLegibility; margin-top: 1em; margin-bottom: 0.5em; line-height: 1.2125em; }
h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #e99b8f; line-height: 0; }
h1 { font-size: 2.125em; }
h2 { font-size: 1.6875em; }
h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
h4 { font-size: 1.125em; }
h5 { font-size: 1.125em; }
h6 { font-size: 1em; }
hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
em, i { font-style: italic; line-height: inherit; }
strong, b { font-weight: bold; line-height: inherit; }
small { font-size: 60%; line-height: inherit; }
code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; color: #060; }
ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; list-style-position: outside; font-family: inherit; }
ul, ol { margin-left: 1.5em; }
ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; }
ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
ul.square { list-style-type: square; }
ul.circle { list-style-type: circle; }
ul.disc { list-style-type: disc; }
ul.no-bullet { list-style: none; }
ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
dl dt { margin-bottom: 0.3125em; font-weight: bold; }
dl dd { margin-bottom: 1.25em; }
abbr, acronym { text-transform: uppercase; font-size: 90%; color: #222222; border-bottom: 1px dotted #dddddd; cursor: help; }
abbr { text-transform: none; }
blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
blockquote cite { display: block; font-size: inherit; color: #555555; }
blockquote cite:before { content: "\2014 \0020"; }
blockquote cite a, blockquote cite a:visited { color: #555555; }
blockquote, blockquote p { line-height: 1.6; color: #6f6f6f; }
.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; }
.vcard li { margin: 0; display: block; }
.vcard .fn { font-weight: bold; font-size: 0.9375em; }
.vevent .summary { font-weight: bold; }
.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
h1 { font-size: 2.75em; }
h2 { font-size: 2.3125em; }
h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
h4 { font-size: 1.4375em; } }
.print-only { display: none !important; }
@media print { * { background: transparent !important; color: #000 !important; box-shadow: none !important; text-shadow: none !important; }
a, a:visited { text-decoration: underline; }
a[href]:after { content: " (" attr(href) ")"; }
abbr[title]:after { content: " (" attr(title) ")"; }
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
thead { display: table-header-group; }
tr, img { page-break-inside: avoid; }
img { max-width: 100% !important; }
@page { margin: 0.5cm; }
p, h2, h3, #toctitle, .sidebarblock > .content > .title { orphans: 3; widows: 3; }
h2, h3, #toctitle, .sidebarblock > .content > .title { page-break-after: avoid; }
.hide-on-print { display: none !important; }
.print-only { display: block !important; }
.hide-for-print { display: none !important; }
.show-for-print { display: inherit !important; } }
table { background: white; margin-bottom: 1.25em; border: solid 1px #dddddd; }
table thead, table tfoot { background: whitesmoke; font-weight: bold; }
table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: #222222; text-align: left; }
table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #222222; }
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #f9f9f9; }
table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.6; }
.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
.clearfix:after, .float-group:after { clear: both; }
*:not(pre) > code { font-size: 0.9375em; padding: 1px 3px 0; white-space: nowrap; background-color: #f2f2f2; border: 1px solid #cccccc; -webkit-border-radius: 4px; border-radius: 4px; text-shadow: none; }
pre, pre > code { line-height: 1.4; color: inherit; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; }
kbd.keyseq { color: #555555; }
kbd:not(.keyseq) { display: inline-block; color: #222222; font-size: 0.75em; line-height: 1.4; background-color: #F7F7F7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 2px white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; }
kbd kbd:first-child { margin-left: 0; }
kbd kbd:last-child { margin-right: 0; }
.menuseq, .menu { color: #090909; }
p a > code:hover { color: #561309; }
#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
#header { margin-bottom: 2.5em; }
#header > h1 { color: black; font-weight: normal; border-bottom: 1px solid #dddddd; margin-bottom: -28px; padding-bottom: 32px; }
#header span { color: #6f6f6f; }
#header #revnumber { text-transform: capitalize; }
#header br { display: none; }
#header br + span { padding-left: 3px; }
#header br + span:before { content: "\2013 \0020"; }
#header br + span.author { padding-left: 0; }
#header br + span.author:before { content: ", "; }
#toc { border-bottom: 3px double #ebebeb; padding-bottom: 1.25em; }
#toc > ul { margin-left: 0.25em; }
#toc ul.sectlevel0 > li > a { font-style: italic; }
#toc ul.sectlevel0 ul.sectlevel1 { margin-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
#toc ul { list-style-type: none; }
#toctitle { color: #7a2518; }
@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; }
#toc.toc2 { position: fixed; width: 20em; left: 0; top: 0; border-right: 1px solid #ebebeb; border-bottom: 0; z-index: 1000; padding: 1em; height: 100%; overflow: auto; }
#toc.toc2 #toctitle { margin-top: 0; }
#toc.toc2 > ul { font-size: .95em; }
#toc.toc2 ul ul { margin-left: 0; padding-left: 1.25em; }
#toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
body.toc2.toc-right { padding-left: 0; padding-right: 20em; }
body.toc2.toc-right #toc.toc2 { border-right: 0; border-left: 1px solid #ebebeb; left: auto; right: 0; } }
#content #toc { border-style: solid; border-width: 1px; border-color: #d9d9d9; margin-bottom: 1.25em; padding: 1.25em; background: #f2f2f2; border-width: 0; -webkit-border-radius: 4px; border-radius: 4px; }
#content #toc > :first-child { margin-top: 0; }
#content #toc > :last-child { margin-bottom: 0; }
#content #toc a { text-decoration: none; }
#content #toctitle { font-weight: bold; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-size: 1em; padding-left: 0.125em; }
#footer { max-width: 100%; background-color: #222222; padding: 1.25em; }
#footer-text { color: #dddddd; line-height: 1.44; }
.sect1 { padding-bottom: 1.25em; }
.sect1 + .sect1 { border-top: 3px double #ebebeb; }
#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; width: 1em; margin-left: -1em; display: block; text-decoration: none; visibility: hidden; text-align: center; font-weight: normal; }
#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: '\00A7'; font-size: .85em; vertical-align: text-top; display: block; margin-top: 0.05em; }
#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #ba3925; text-decoration: none; }
#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #a53221; }
.imageblock, .literalblock, .listingblock, .verseblock, .videoblock { margin-bottom: 1.25em; }
.admonitionblock td.content > .title, .exampleblock > .title, .imageblock > .title, .videoblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, .sidebarblock > .title, .tableblock > .title, .verseblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-align: left; font-weight: bold; }
.tableblock > caption { text-align: left; font-weight: bold; white-space: nowrap; overflow: visible; max-width: 0; }
table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; }
.admonitionblock > table { border: 0; background: none; width: 100%; }
.admonitionblock > table td.icon { text-align: center; width: 80px; }
.admonitionblock > table td.icon img { max-width: none; }
.admonitionblock > table td.icon .title { font-weight: bold; text-transform: uppercase; }
.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #6f6f6f; }
.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 4px; border-radius: 4px; }
.exampleblock > .content > :first-child { margin-top: 0; }
.exampleblock > .content > :last-child { margin-bottom: 0; }
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6, .exampleblock > .content p { color: #333333; }
.exampleblock > .content h1, .exampleblock > .content h2, .exampleblock > .content h3, .exampleblock > .content #toctitle, .sidebarblock.exampleblock > .content > .title, .exampleblock > .content h4, .exampleblock > .content h5, .exampleblock > .content h6 { line-height: 1; margin-bottom: 0.625em; }
.exampleblock > .content h1.subheader, .exampleblock > .content h2.subheader, .exampleblock > .content h3.subheader, .exampleblock > .content .subheader#toctitle, .sidebarblock.exampleblock > .content > .subheader.title, .exampleblock > .content h4.subheader, .exampleblock > .content h5.subheader, .exampleblock > .content h6.subheader { line-height: 1.4; }
.exampleblock.result > .content { -webkit-box-shadow: 0 1px 8px #d9d9d9; box-shadow: 0 1px 8px #d9d9d9; }
.sidebarblock { border-style: solid; border-width: 1px; border-color: #d9d9d9; margin-bottom: 1.25em; padding: 1.25em; background: #f2f2f2; -webkit-border-radius: 4px; border-radius: 4px; }
.sidebarblock > :first-child { margin-top: 0; }
.sidebarblock > :last-child { margin-bottom: 0; }
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6, .sidebarblock p { color: #333333; }
.sidebarblock h1, .sidebarblock h2, .sidebarblock h3, .sidebarblock #toctitle, .sidebarblock > .content > .title, .sidebarblock h4, .sidebarblock h5, .sidebarblock h6 { line-height: 1; margin-bottom: 0.625em; }
.sidebarblock h1.subheader, .sidebarblock h2.subheader, .sidebarblock h3.subheader, .sidebarblock .subheader#toctitle, .sidebarblock > .content > .subheader.title, .sidebarblock h4.subheader, .sidebarblock h5.subheader, .sidebarblock h6.subheader { line-height: 1.4; }
.sidebarblock > .content > .title { color: #7a2518; margin-top: 0; line-height: 1.6; }
.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
.literalblock > .content pre, .listingblock > .content pre { background: none; border-width: 1px 0; border-style: dotted; border-color: #bfbfbf; -webkit-border-radius: 4px; border-radius: 4px; padding: 0.75em 0.75em 0.5em 0.75em; word-wrap: break-word; }
.literalblock > .content pre.nowrap, .listingblock > .content pre.nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
.literalblock > .content pre > code, .listingblock > .content pre > code { display: block; }
@media only screen { .literalblock > .content pre, .listingblock > .content pre { font-size: 0.8em; } }
@media only screen and (min-width: 768px) { .literalblock > .content pre, .listingblock > .content pre { font-size: 0.9em; } }
@media only screen and (min-width: 1280px) { .literalblock > .content pre, .listingblock > .content pre { font-size: 1em; } }
.listingblock > .content { position: relative; }
.listingblock:hover code[class*=" language-"]:before { text-transform: uppercase; font-size: 0.9em; color: #999; position: absolute; top: 0.375em; right: 0.375em; }
.listingblock:hover code.asciidoc:before { content: "asciidoc"; }
.listingblock:hover code.clojure:before { content: "clojure"; }
.listingblock:hover code.css:before { content: "css"; }
.listingblock:hover code.groovy:before { content: "groovy"; }
.listingblock:hover code.html:before { content: "html"; }
.listingblock:hover code.java:before { content: "java"; }
.listingblock:hover code.javascript:before { content: "javascript"; }
.listingblock:hover code.python:before { content: "python"; }
.listingblock:hover code.ruby:before { content: "ruby"; }
.listingblock:hover code.scss:before { content: "scss"; }
.listingblock:hover code.xml:before { content: "xml"; }
.listingblock:hover code.yaml:before { content: "yaml"; }
.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
.listingblock.terminal pre .command:not([data-prompt]):before { content: '$'; }
table.pyhltable { border: 0; margin-bottom: 0; }
table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; }
table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
.highlight.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; }
.highlight.pygments .lineno { display: inline-block; margin-right: .25em; }
table.pyhltable .linenodiv { background-color: transparent !important; padding-right: 0 !important; }
.quoteblock { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; }
.quoteblock blockquote { margin: 0 0 1.25em 0; padding: 0 0 0.5625em 0; border: 0; }
.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
.quoteblock .attribution { margin-top: -.25em; padding-bottom: 0.5625em; font-size: inherit; color: #555555; }
.quoteblock .attribution br { display: none; }
.quoteblock .attribution cite { display: block; margin-bottom: 0.625em; }
table thead th, table tfoot th { font-weight: bold; }
table.tableblock.grid-all { border-collapse: separate; border-spacing: 1px; -webkit-border-radius: 4px; border-radius: 4px; border-top: 1px solid #dddddd; border-bottom: 1px solid #dddddd; }
table.tableblock.frame-topbot, table.tableblock.frame-none { border-left: 0; border-right: 0; }
table.tableblock.frame-sides, table.tableblock.frame-none { border-top: 0; border-bottom: 0; }
table.tableblock td .paragraph:last-child p, table.tableblock td > p:last-child { margin-bottom: 0; }
th.tableblock.halign-left, td.tableblock.halign-left { text-align: left; }
th.tableblock.halign-right, td.tableblock.halign-right { text-align: right; }
th.tableblock.halign-center, td.tableblock.halign-center { text-align: center; }
th.tableblock.valign-top, td.tableblock.valign-top { vertical-align: top; }
th.tableblock.valign-bottom, td.tableblock.valign-bottom { vertical-align: bottom; }
th.tableblock.valign-middle, td.tableblock.valign-middle { vertical-align: middle; }
p.tableblock.header { color: #222222; font-weight: bold; }
td > div.verse { white-space: pre; }
ol { margin-left: 1.75em; }
ul li ol { margin-left: 1.5em; }
dl dd { margin-left: 1.125em; }
dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.625em; }
ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; }
ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; }
ul.checklist li > p:first-child > i[class^="icon-check"]:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
ul.checklist li > p:first-child > input[type="checkbox"]:first-child { position: relative; top: 1px; }
ul.inline { margin: 0 auto 0.625em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; }
ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; }
ul.inline > li > * { display: block; }
.unstyled dl dt { font-weight: normal; font-style: normal; }
ol.arabic { list-style-type: decimal; }
ol.decimal { list-style-type: decimal-leading-zero; }
ol.loweralpha { list-style-type: lower-alpha; }
ol.upperalpha { list-style-type: upper-alpha; }
ol.lowerroman { list-style-type: lower-roman; }
ol.upperroman { list-style-type: upper-roman; }
ol.lowergreek { list-style-type: lower-greek; }
.hdlist > table, .colist > table { border: 0; background: none; }
.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
td.hdlist1 { padding-right: .8em; font-weight: bold; }
td.hdlist1, td.hdlist2 { vertical-align: top; }
.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
.colist > table tr > td:first-of-type { padding: 0 .8em; line-height: 1; }
.colist > table tr > td:last-of-type { padding: 0.25em 0; }
.qanda > ol > li > p > em:only-child { color: #00467f; }
.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; }
.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; }
.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; }
.imageblock > .title { margin-bottom: 0; }
.imageblock.thumb, .imageblock.th { border-width: 6px; }
.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
.image.left { margin-right: 0.625em; }
.image.right { margin-left: 0.625em; }
a.image { text-decoration: none; }
span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; }
span.footnote a, span.footnoteref a { text-decoration: none; }
#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; }
#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; }
#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; }
#footnotes .footnote:last-of-type { margin-bottom: 0; }
#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
.gist .file-data > table { border: none; background: #fff; width: 100%; margin-bottom: 0; }
.gist .file-data > table td.line-data { width: 99%; }
div.unbreakable { page-break-inside: avoid; }
.big { font-size: larger; }
.small { font-size: smaller; }
.underline { text-decoration: underline; }
.overline { text-decoration: overline; }
.line-through { text-decoration: line-through; }
.aqua { color: #00bfbf; }
.aqua-background { background-color: #00fafa; }
.black { color: black; }
.black-background { background-color: black; }
.blue { color: #0000bf; }
.blue-background { background-color: #0000fa; }
.fuchsia { color: #bf00bf; }
.fuchsia-background { background-color: #fa00fa; }
.gray { color: #606060; }
.gray-background { background-color: #7d7d7d; }
.green { color: #006000; }
.green-background { background-color: #007d00; }
.lime { color: #00bf00; }
.lime-background { background-color: #00fa00; }
.maroon { color: #600000; }
.maroon-background { background-color: #7d0000; }
.navy { color: #000060; }
.navy-background { background-color: #00007d; }
.olive { color: #606000; }
.olive-background { background-color: #7d7d00; }
.purple { color: #600060; }
.purple-background { background-color: #7d007d; }
.red { color: #bf0000; }
.red-background { background-color: #fa0000; }
.silver { color: #909090; }
.silver-background { background-color: #bcbcbc; }
.teal { color: #006060; }
.teal-background { background-color: #007d7d; }
.white { color: #bfbfbf; }
.white-background { background-color: #fafafa; }
.yellow { color: #bfbf00; }
.yellow-background { background-color: #fafa00; }
span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
.admonitionblock td.icon [class^="icon-"]:before { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #005498; color: #003f72; }
.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
.conum { display: inline-block; color: white !important; background-color: #222222; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; width: 20px; height: 20px; font-size: 12px; font-weight: bold; line-height: 20px; font-family: Arial, sans-serif; font-style: normal; position: relative; top: -2px; letter-spacing: -1px; }
.conum * { color: white !important; }
.conum + b { display: none; }
.conum:after { content: attr(data-value); }
.conum:not([data-value]):empty { display: none; }
.literalblock > .content > pre, .listingblock > .content > pre { -webkit-border-radius: 0; border-radius: 0; }
/** Spring IO customizations **/
h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { color: #060; }
.subheader, #content #toctitle, .admonitionblock td.content > .title, .exampleblock > .title, .imageblock > .title, .videoblock > .title, .listingblock > .title, .literalblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, .sidebarblock > .title, .tableblock > .title, .verseblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title, .tableblock > caption { color: #080; }