Document provisioner service viz applications, tenants and clients
diff --git a/component-test/build.gradle b/component-test/build.gradle
index aa3d249..37e9698 100644
--- a/component-test/build.gradle
+++ b/component-test/build.gradle
@@ -26,6 +26,7 @@
 
     dependencies {
         classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+        classpath("org.asciidoctor:asciidoctor-gradle-plugin:1.5.3")
     }
 }
 
@@ -35,6 +36,7 @@
 }
 
 apply from: '../shared.gradle'
+apply plugin: 'org.asciidoctor.convert'
 
 dependencies {
     compile(
@@ -47,9 +49,18 @@
             [group: 'org.apache.fineract.cn', name: 'test', version: versions.frameworktest],
             [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
             [group: 'org.springframework.boot', name: 'spring-boot-starter-test'],
+            [group: 'org.springframework.restdocs', name: 'spring-restdocs-mockmvc'],
+            [group: 'junit', name: 'junit', version: '4.12']
     )
 }
 
+asciidoctor {
+    sourceDir 'build/doc/asciidoc/'
+    outputDir 'build/doc/html5'
+    options backend: "html", doctype: "book"
+    attributes "source-highlighter": "highlightjs", 'snippets': file('build/doc/generated-snippets/')
+}
+
 publishing {
     publications {
         mavenJava(MavenPublication) {
diff --git a/component-test/src/main/java/org/apache/fineract/cn/provisioner/application/ApplicationsApiDocumentation.java b/component-test/src/main/java/org/apache/fineract/cn/provisioner/application/ApplicationsApiDocumentation.java
new file mode 100644
index 0000000..e592563
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/provisioner/application/ApplicationsApiDocumentation.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.provisioner.application;
+
+import com.google.gson.Gson;
+import org.apache.fineract.cn.api.context.AutoSeshat;
+import org.apache.fineract.cn.api.util.ApiConstants;
+import org.apache.fineract.cn.provisioner.api.v1.domain.Application;
+import org.apache.fineract.cn.provisioner.api.v1.domain.AuthenticationResponse;
+import org.apache.fineract.cn.provisioner.config.ProvisionerConstants;
+import org.junit.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
+import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
+import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
+
+import org.apache.fineract.cn.provisioner.AbstractServiceTest;
+
+public class ApplicationsApiDocumentation extends AbstractServiceTest {
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build/doc/generated-snippets/test-application");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  private AutoSeshat autoSeshat;
+
+  @Before
+  public void setUp ( ) {
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .build();
+  }
+
+  @Before
+  public void before ( ) {
+    final AuthenticationResponse authentication = provisioner.authenticate(
+            this.getClientId(), ApiConstants.SYSTEM_SU, ProvisionerConstants.INITIAL_PWD);
+    autoSeshat = new AutoSeshat(authentication.getToken());
+  }
+
+  @After
+  public void after ( ) {
+    provisioner.deleteApplication(Fixture.getApplication().getName());
+    autoSeshat.close();
+  }
+
+  @Test
+  public void documentCreateApplication ( ) throws Exception {
+    final Application application = Fixture.getApplication();
+
+    Gson gson = new Gson();
+    this.mockMvc.perform(post("/applications")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(gson.toJson(application)))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-create-application", preprocessRequest(prettyPrint()),
+                    requestFields(
+                            fieldWithPath("name").description("Application's name"),
+                            fieldWithPath("description").description("Application's description"),
+                            fieldWithPath("vendor").description("Application's vendor"),
+                            fieldWithPath("homepage").description("Application's homepage")
+                    )
+            ));
+  }
+
+  @Test
+  public void shouldFindApplication ( ) throws Exception {
+    Application application = new Application();
+    application.setName("comp-test-app");
+    application.setDescription("Component Test Application");
+    application.setHomepage("http://www.component.test");
+    application.setVendor("Component Test");
+
+    provisioner.createApplication(application);
+
+    this.mockMvc.perform(get("/applications/" + application.getName())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-find-application", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("name").description("Application's name"),
+                            fieldWithPath("description").description("Application's description"),
+                            fieldWithPath("vendor").description("Application's vendor"),
+                            fieldWithPath("homepage").description("Application's homepage")
+                    )
+            ));
+  }
+
+  @Test
+  public void documentFetchApplications ( ) throws Exception {
+    Application firstApplication = new Application();
+    firstApplication.setName("first-comp-test-app");
+    firstApplication.setDescription("First Component Test Application");
+    firstApplication.setHomepage("http://www.first-component.test");
+    firstApplication.setVendor("First Component Test");
+
+    Application secondApplication = new Application();
+    secondApplication.setName("second-comp-test-app");
+    secondApplication.setDescription("Second Component Test Application");
+    secondApplication.setHomepage("http://www.second-component.test");
+    secondApplication.setVendor("Second Component Test");
+
+    provisioner.createApplication(firstApplication);
+    provisioner.createApplication(secondApplication);
+
+    this.mockMvc.perform(get("/applications")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-fetch-applications", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("[].name").description("First Application's name"),
+                            fieldWithPath("[].description").description("First Application's description"),
+                            fieldWithPath("[].vendor").description("First Application's vendor"),
+                            fieldWithPath("[].homepage").description("First Application's homepage"),
+                            fieldWithPath("[1].name").description("Second Application's name"),
+                            fieldWithPath("[1].description").description("Second Application's description"),
+                            fieldWithPath("[1].vendor").description("Second Application's vendor"),
+                            fieldWithPath("[1].homepage").description("Second Application's homepage")
+                    )
+            ));
+  }
+
+  @Test
+  public void documentDeleteApplication ( ) throws Exception {
+    Application randApplication = new Application();
+    randApplication.setName("random-comp-test-app");
+    randApplication.setDescription("Random Component Test Application");
+    randApplication.setHomepage("http://www.random-component.test");
+    randApplication.setVendor("Random Component Test");
+
+    provisioner.createApplication(randApplication);
+
+    this.mockMvc.perform(delete("/applications/" + randApplication.getName())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-delete-application"));
+  }
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/ClientsApiDocumentation.java b/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/ClientsApiDocumentation.java
new file mode 100644
index 0000000..9cee07e
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/ClientsApiDocumentation.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.provisioner.client;
+
+import com.google.gson.Gson;
+import org.apache.fineract.cn.api.context.AutoSeshat;
+import org.apache.fineract.cn.api.util.ApiConstants;
+import org.apache.fineract.cn.provisioner.AbstractServiceTest;
+import org.apache.fineract.cn.provisioner.api.v1.domain.AuthenticationResponse;
+import org.apache.fineract.cn.provisioner.api.v1.domain.Client;
+import org.apache.fineract.cn.provisioner.config.ProvisionerConstants;
+import org.junit.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
+import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
+import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class ClientsApiDocumentation extends AbstractServiceTest {
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build/doc/generated-snippets/test-client");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  private AutoSeshat autoSeshat;
+
+  @Before
+  public void setUp ( ) {
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .build();
+  }
+
+  @Before
+  public void before ( ) {
+    final AuthenticationResponse authentication = provisioner.authenticate(
+            this.getClientId(), ApiConstants.SYSTEM_SU, ProvisionerConstants.INITIAL_PWD);
+    autoSeshat = new AutoSeshat(authentication.getToken());
+  }
+
+  @After
+  public void after ( ) {
+    provisioner.deleteClient(Fixture.getCompTestClient().getName());
+    autoSeshat.close();
+  }
+
+  @Test
+  public void documentCreateClient ( ) throws Exception {
+    final Client client = Fixture.getCompTestClient();
+
+    Gson gson = new Gson();
+    this.mockMvc.perform(post("/clients")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(gson.toJson(client)))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-create-client", preprocessRequest(prettyPrint()),
+                    requestFields(
+                            fieldWithPath("name").description("Client's name"),
+                            fieldWithPath("description").description("Client's description"),
+                            fieldWithPath("redirectUri").description("Client's Redirect URI"),
+                            fieldWithPath("vendor").description("Client's vendor"),
+                            fieldWithPath("homepage").description("Client's Homepage"))));
+  }
+
+  @Test
+  public void documentFindClient ( ) throws Exception {
+    final Client client = Fixture.getCompTestClient();
+    provisioner.createClient(client);
+
+    this.mockMvc.perform(get("/clients/" + client.getName())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-find-client", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("name").description("Client's name"),
+                            fieldWithPath("description").description("Client's description"),
+                            fieldWithPath("redirectUri").description("Client's Redirect URI"),
+                            fieldWithPath("vendor").description("Client's vendor"),
+                            fieldWithPath("homepage").description("Client's Homepage"))));
+  }
+
+  @Test
+  public void documentFetchClients ( ) throws Exception {
+    final Client firstClient = new Client();
+    firstClient.setName("client-comp-test-hd8");
+    firstClient.setDescription("Component Test Client Descr hd8");
+    firstClient.setHomepage("http://hd8.example.org");
+    firstClient.setVendor("Component Test Vendor hd8");
+    firstClient.setRedirectUri("http://hd8.redirect.me");
+    provisioner.createClient(firstClient);
+
+    final Client secondClient = Fixture.getCompTestClient();
+    secondClient.setName("client-comp-test-832");
+    secondClient.setDescription("Component Test Client Descr 832");
+    secondClient.setHomepage("http://832.example.org");
+    secondClient.setVendor("Component Test Vendor 832");
+    secondClient.setRedirectUri("http://832.redirect.me");
+    provisioner.createClient(secondClient);
+
+    this.mockMvc.perform(get("/clients")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-fetch-clients", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("[].name").description("First Client's name"),
+                            fieldWithPath("[].description").description("First Client's description"),
+                            fieldWithPath("[].redirectUri").description("First Client's Redirect URI"),
+                            fieldWithPath("[].vendor").description("First Client's vendor"),
+                            fieldWithPath("[].homepage").description("First Client's Homepage"),
+                            fieldWithPath("[1].name").description("Second Client's name"),
+                            fieldWithPath("[1].description").description("Second Client's description"),
+                            fieldWithPath("[1].redirectUri").description("Second Client's Redirect URI"),
+                            fieldWithPath("[1].vendor").description("Second Client's vendor"),
+                            fieldWithPath("[1].homepage").description("Second Client's Homepage")
+                    )));
+  }
+
+  @Test
+  public void documentDeleteClient ( ) throws Exception {
+    final Client firstClient = Fixture.getCompTestClient();
+    provisioner.createClient(firstClient);
+
+    this.mockMvc.perform(delete("/clients/" + firstClient.getName())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-delete-client"));
+  }
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/Fixture.java b/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/Fixture.java
index 0776c88..2381d6b 100644
--- a/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/Fixture.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/provisioner/client/Fixture.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.cn.provisioner.client;
 
+import org.apache.commons.lang.RandomStringUtils;
 import org.apache.fineract.cn.provisioner.api.v1.domain.Client;
 
 class Fixture {
@@ -25,11 +26,11 @@
   private static Client compTestClient = new Client();
 
   static {
-    compTestClient.setName("comp-test");
-    compTestClient.setDescription("Component Test Client");
-    compTestClient.setHomepage("http://www.example.org");
-    compTestClient.setVendor("Component Test");
-    compTestClient.setRedirectUri("http://redirect.me");
+    compTestClient.setName("client-comp-test-" + RandomStringUtils.randomAlphanumeric(5));
+    compTestClient.setDescription("Component Test Client Descr " + RandomStringUtils.randomAlphanumeric(5));
+    compTestClient.setHomepage("http://" + RandomStringUtils.randomAlphanumeric(5) + ".example.org");
+    compTestClient.setVendor("Component Test Vendor " + RandomStringUtils.randomAlphanumeric(5));
+    compTestClient.setRedirectUri("http://" + RandomStringUtils.randomAlphanumeric(5) + ".redirect.me");
   }
 
   private Fixture() {
diff --git a/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/Fixture.java b/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/Fixture.java
index 68a442c..623282c 100644
--- a/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/Fixture.java
+++ b/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/Fixture.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.cn.provisioner.tenant;
 
 
+import org.apache.commons.lang.RandomStringUtils;
 import org.apache.fineract.cn.provisioner.api.v1.domain.CassandraConnectionInfo;
 import org.apache.fineract.cn.provisioner.api.v1.domain.DatabaseConnectionInfo;
 import org.apache.fineract.cn.provisioner.api.v1.domain.Tenant;
@@ -28,12 +29,12 @@
   static Tenant getCompTestTenant() {
     final Tenant compTestTenant = new Tenant();
     compTestTenant.setIdentifier(TestEnvironment.getRandomTenantName());
-    compTestTenant.setName("Comp Test");
-    compTestTenant.setDescription("Component Test Tenant");
+    compTestTenant.setName("Comp Test " + RandomStringUtils.randomAlphanumeric(4));
+    compTestTenant.setDescription("Component Test Tenant " + RandomStringUtils.randomAlphabetic(4));
 
     final CassandraConnectionInfo cassandraConnectionInfo = new CassandraConnectionInfo();
     compTestTenant.setCassandraConnectionInfo(cassandraConnectionInfo);
-    cassandraConnectionInfo.setClusterName("Test Cluster");
+    cassandraConnectionInfo.setClusterName("Test Cluster" + RandomStringUtils.randomAlphabetic(3));
     cassandraConnectionInfo.setContactPoints("127.0.0.1:9142");
     cassandraConnectionInfo.setKeyspace(compTestTenant.getIdentifier());
     cassandraConnectionInfo.setReplicas("3");
diff --git a/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/TenantApiDocumentation.java b/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/TenantApiDocumentation.java
new file mode 100644
index 0000000..414b61e
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/provisioner/tenant/TenantApiDocumentation.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.provisioner.tenant;
+
+import com.google.gson.Gson;
+import org.apache.fineract.cn.api.context.AutoSeshat;
+import org.apache.fineract.cn.api.util.ApiConstants;
+import org.apache.fineract.cn.provisioner.AbstractServiceTest;
+import org.apache.fineract.cn.provisioner.api.v1.domain.*;
+import org.apache.fineract.cn.provisioner.config.ProvisionerConstants;
+import org.junit.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.restdocs.JUnitRestDocumentation;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
+import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
+import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
+import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
+import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
+import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
+import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public class TenantApiDocumentation extends AbstractServiceTest {
+  @Rule
+  public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("build/doc/generated-snippets/test-tenant");
+
+  @Autowired
+  private WebApplicationContext context;
+
+  private MockMvc mockMvc;
+
+  private AutoSeshat autoSeshat;
+
+  @Before
+  public void setUp ( ) {
+
+    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+            .apply(documentationConfiguration(this.restDocumentation))
+            .build();
+  }
+
+  @Before
+  public void before ( ) {
+    final AuthenticationResponse authentication = provisioner.authenticate(
+            this.getClientId(), ApiConstants.SYSTEM_SU, ProvisionerConstants.INITIAL_PWD);
+    autoSeshat = new AutoSeshat(authentication.getToken());
+  }
+
+  @After
+  public void after ( ) throws InterruptedException {
+    //provisioner.deleteTenant(Fixture.getCompTestTenant().getIdentifier());
+    autoSeshat.close();
+  }
+
+  @Test
+  public void documentCreateTenant ( ) throws Exception {
+    final Tenant myTenant = Fixture.getCompTestTenant();
+
+    Gson gson = new Gson();
+    this.mockMvc.perform(post("/tenants")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE)
+            .content(gson.toJson(myTenant)))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-create-tenant", preprocessRequest(prettyPrint()),
+                    requestFields(
+                            fieldWithPath("identifier").description("Tenant's Identifier"),
+                            fieldWithPath("name").description("Tenant's name"),
+                            fieldWithPath("description").description("Tenant's description"),
+                            fieldWithPath("cassandraConnectionInfo").type("CassandraConnectionInfo").description("Tenant's Cassandra Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _CassandraConnectionInfo_ { +\n" +
+                                    "    String clusterName; +\n" +
+                                    "    String contactPoints; +\n" +
+                                    "    String keyspace; +\n" +
+                                    "    String replicationType; +\n" +
+                                    "    String replicas; +\n" +
+                                    "  } +"),
+                            fieldWithPath("databaseConnectionInfo").type("_DatabaseConnectionInfo_").description("Tenant's Database Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _DatabaseConnectionInfo_ { +\n" +
+                                    "    String driverClass; +\n" +
+                                    "    String databaseName; +\n" +
+                                    "    String host; +\n" +
+                                    "    String port; +\n" +
+                                    "    String user; +\n" +
+                                    "    String password; +\n" +
+                                    "  } +")
+                    )
+            ));
+  }
+
+  @Test
+  public void documentFindTenant ( ) throws Exception {
+    final Tenant mytenant = Fixture.getCompTestTenant();
+    provisioner.createTenant(mytenant);
+
+    this.mockMvc.perform(get("/tenants/" + mytenant.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-find-tenant", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("identifier").description("Tenant's Identifier"),
+                            fieldWithPath("name").description("Tenant's name"),
+                            fieldWithPath("description").description("Tenant's description"),
+                            fieldWithPath("cassandraConnectionInfo").type("CassandraConnectionInfo").description("Tenant's Cassandra Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _CassandraConnectionInfo_ { +\n" +
+                                    "    String clusterName; +\n" +
+                                    "    String contactPoints; +\n" +
+                                    "    String keyspace; +\n" +
+                                    "    String replicationType; +\n" +
+                                    "    String replicas; +\n" +
+                                    "  } +"),
+                            fieldWithPath("databaseConnectionInfo").type("_DatabaseConnectionInfo_").description("Tenant's Database Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _DatabaseConnectionInfo_ { +\n" +
+                                    "    String driverClass; +\n" +
+                                    "    String databaseName; +\n" +
+                                    "    String host; +\n" +
+                                    "    String port; +\n" +
+                                    "    String user; +\n" +
+                                    "    String password; +\n" +
+                                    "  } +")
+                    )
+            ));
+  }
+
+  @Test
+  public void documentFetchTenants ( ) throws Exception {
+    final Tenant firstTenant = Fixture.getCompTestTenant();
+    provisioner.createTenant(firstTenant);
+
+    final Tenant secondTenant = Fixture.getCompTestTenant();
+    provisioner.createTenant(secondTenant);
+
+    this.mockMvc.perform(get("/tenants")
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isOk())
+            .andDo(document("document-fetch-tenants", preprocessResponse(prettyPrint()),
+                    responseFields(
+                            fieldWithPath("[].identifier").description("Tenant's Identifier"),
+                            fieldWithPath("[].name").description("Tenant's name"),
+                            fieldWithPath("[].description").description("Tenant's description"),
+                            fieldWithPath("[].cassandraConnectionInfo").type("CassandraConnectionInfo").description("Tenant's Cassandra Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _CassandraConnectionInfo_ { +\n" +
+                                    "    String clusterName; +\n" +
+                                    "    String contactPoints; +\n" +
+                                    "    String keyspace; +\n" +
+                                    "    String replicationType; +\n" +
+                                    "    String replicas; +\n" +
+                                    "  } +"),
+                            fieldWithPath("[].databaseConnectionInfo").type("_DatabaseConnectionInfo_").description("Tenant's Database Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _DatabaseConnectionInfo_ { +\n" +
+                                    "    String driverClass; +\n" +
+                                    "    String databaseName; +\n" +
+                                    "    String host; +\n" +
+                                    "    String port; +\n" +
+                                    "    String user; +\n" +
+                                    "    String password; +\n" +
+                                    "  } +"),
+                            fieldWithPath("[1].identifier").description("Tenant's Identifier"),
+                            fieldWithPath("[1].name").description("Tenant's name"),
+                            fieldWithPath("[1].description").description("Tenant's description"),
+                            fieldWithPath("[1].cassandraConnectionInfo").type("CassandraConnectionInfo").description("Tenant's Cassandra Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _CassandraConnectionInfo_ { +\n" +
+                                    "    String clusterName; +\n" +
+                                    "    String contactPoints; +\n" +
+                                    "    String keyspace; +\n" +
+                                    "    String replicationType; +\n" +
+                                    "    String replicas; +\n" +
+                                    "  } +"),
+                            fieldWithPath("[1].databaseConnectionInfo").type("_DatabaseConnectionInfo_").description("Tenant's Database Connection Information +\n" +
+                                    " +\n" +
+                                    "*class* _DatabaseConnectionInfo_ { +\n" +
+                                    "    String driverClass; +\n" +
+                                    "    String databaseName; +\n" +
+                                    "    String host; +\n" +
+                                    "    String port; +\n" +
+                                    "    String user; +\n" +
+                                    "    String password; +\n" +
+                                    "  } +")
+                    )
+            ));
+  }
+
+  @Test
+  public void documentDeleteTenant ( ) throws Exception {
+    final Tenant firstTenant = Fixture.getCompTestTenant();
+    provisioner.createTenant(firstTenant);
+
+    this.mockMvc.perform(delete("/tenants/" + firstTenant.getIdentifier())
+            .accept(MediaType.APPLICATION_JSON_VALUE)
+            .contentType(MediaType.APPLICATION_JSON_VALUE))
+            .andExpect(status().isAccepted())
+            .andDo(document("document-delete-tenant"));
+  }
+}