docs(dev-guide): fix callouts and use Asciidoc-style code blocks
MODIFY
docs/modules/ROOT/pages/development/Plugins.adoc
docs/modules/ROOT/pages/development/Plugins.adoc
@@ -9,21 +9,23 @@ in the form of JARs, the WAR format is a natural choice.
In addition to the standard layout of a Java Web Archive, an apiman plugin must contain
the following plugin specification file (which contains information about the plugin):
-```
+[source]
+----
META-INF/apiman/plugin.json
-```
+----
This 'plugin.json' file contains the basic meta-data that describes the plugin, and
should be of the following format:
-```json
+[source,json]
+----
{
"frameworkVersion" : 1.0,
"name" : "Plugin Name",
"description" : "A plugin description goes here.",
"version" : "3.1.9"
}
-```
+----
* *frameworkVersion*: Indicates the apiman plugin framework version this plugin is compatible with - this should simply be 1.0 for now (reserved for future use)
* *name*: The name of the plugin.
@@ -43,13 +45,15 @@ https://github.com/apiman/apiman-plugins/tree/master/noop-policy
In order to create an apiman plugin using maven, simply create a new maven project
and set its 'packaging' type to *war*.
-```xml
+[source,xml]
+----
<packaging>war</packaging>
-```
+----
Next, obviously feel free to include any dependencies you might need:
-```xml
+[source,xml]
+----
<dependencies>
<!-- apiman dependencies (must be excluded from the WAR) -->
<dependency>
@@ -58,7 +62,7 @@ Next, obviously feel free to include any dependencies you might need:
<scope>provided</scope>
</dependency>
</dependencies>
-```
+----
You'll want to make any apiman dependencies provided so that there aren't any classloading
conflicts when executing your code.
@@ -66,14 +70,16 @@ conflicts when executing your code.
Finally, we recommend that you put your plugin.json file in the following location
in your maven project:
-```
+[source]
+----
src/main/apiman
-```
+----
Of course, any resoures in that location are not automatially included in the final
WAR, so you should add the following markup to your pom.xml:
-```xml
+[source,xml]
+----
<build>
<plugins>
<plugin>
@@ -92,20 +98,21 @@ WAR, so you should add the following markup to your pom.xml:
</plugin>
</plugins>
</build>
-```
+----
This markup will ensure that resources in the *src/main/apiman* folder will be included
in the correct location in the WAR. Also note that resource filtering is enabled,
which will make it easier to maintain your *plugin.json* file:
-```json
+[source,json]
+----
{
"frameworkVersion" : 1.0,
"name" : "My Plugin Name",
"description" : "My plugin description.",
"version" : "${project.version}"
}
-```
+----
Note that the 'version' of the plugin is set to *${project.version}*, which will get
automatically changed to the version of your maven project at build time.
@@ -158,11 +165,12 @@ All policies must implement the `IPolicy` interface, consisting of several metho
The `apply` method with `ApiRequest` is called during the request phase, and
the `apply` with `ApiResponse` during the response phase:
-```java
+[source,java]
+----
void apply(ApiRequest request, IPolicyContext context, Object config, IPolicyChain<ApiRequest> chain);
void apply(ApiResponse response, IPolicyContext context, Object config, IPolicyChain<ApiResponse> chain);
-```
+----
The API objects, respectively, provide abstracted representations of the head
of a request and response for a given conversation. These can be modified in any
@@ -173,9 +181,10 @@ reason. The IPolicyContext can be used to pass information from the request pha
to the response phase. Any state that must span multiple requests will need to use
one of the policy components described in the *Provided Components* section.
-```java
+[source,java]
+----
Object parseConfiguration(String jsonConfiguration) throws ConfigurationParseException;
-```
+----
The final `IPolicy` method is used to parse JSON configuration into an arbitrary
object configuration which will be passed in in its parsed form to `doApply`, where
@@ -218,11 +227,12 @@ corollaries of `apply`. Implementors must return `IReadWriteStream` streams, whi
apiman uses to write data chunks into policies, and the policies write data to
subsequent policies:
-```java
+[source,java]
+----
IReadWriteStream<ApiRequest> getRequestDataHandler(ApiRequest request, IPolicyContext context);
IReadWriteStream<ApiResponse> getResponseDataHandler(ApiResponse response, IPolicyContext context);
-```
+----
IMPORTANT: Do not return an `IApimanBuffer` with a different native type than you
received. Instantiate new buffers using the `IBufferFactoryComponent` (refer to <<Provided Components>>)
@@ -231,7 +241,8 @@ and prefer append patterns where possible.
Implementors must explicitly hand each chunk onto apiman when they are finished
interacting with it. A convenient way to achieve this is via `AbstractStream<H>`:
-```java
+[source,java]
+----
@Override
public IReadWriteStream<ApiRequest> getRequestDataHandler(final ApiRequest request, final IPolicyContext context) {
return new AbstractStream<ApiRequest>() {
@@ -251,7 +262,7 @@ public IReadWriteStream<ApiRequest> getRequestDataHandler(final ApiRequest reque
}
};
}
-```
+----
IMPORTANT: Do not mutate an `IApimanBuffer` once handed over.
@@ -274,9 +285,10 @@ it depends on, but often times this is unavoidable. Plugins are isolated from o
another, so it is a simple matter of including any required dependencies inside the
plugin's WAR archive in the standard location of:
-```
+[source]
+----
WEB-INF/lib
-```
+----
TIP: You should make sure that any apiman dependencies you use (for example the apiman
core module that contains the IPlugin and other necessary interfaces) are marked
@@ -291,12 +303,13 @@ the functionality.
===== Usage
-```java
+[source,java]
+----
@Override
public void apply(final ApiRequest request, final IPolicyContext context, final Object config,
final IPolicyChain<ApiRequest> chain) {
IApimanLogger logger = context.getLogger(getClass());
- logger.info("Hello, I am an info message in the request"); // 1
+ logger.info("Hello, I am an info message in the request"); // <1>
logger.debug("Hello, I am a debug message in the request");
logger.trace("I am powered by: %s", request.getHeaders().get("X-Powered-By"));
chain.doApply(request);
@@ -306,10 +319,10 @@ the functionality.
public void apply(ApiResponse response, IPolicyContext context, Object config,
IPolicyChain<ApiResponse> chain) {
IApimanLogger logger = context.getLogger(getClass());
- logger.info("Response info message: %d", 42); // 2
+ logger.info("Response info message: %d", 42); // <2>
chain.doApply(response);
}
-```
+----
<1> Consult the interface's javadoc for the full list of available methods.
<2> Format string with arguments.
@@ -319,9 +332,10 @@ which should satisfy most user's requirements.
In `apiman.properties`, provide a reference to the logger factory.
-```properties
+[source,properties]
+----
apiman-gateway.logger-factory=io.apiman.common.logging.slf4j.Slf4jLoggerFactory
-```
+----
Those shipped in the project, are:
@@ -346,16 +360,16 @@ Example IDelegateFactory implementation
public class ExampleLoggerFactory implements IDelegateFactory {
public ExampleLoggerFactory() {}
- public ExampleLoggerFactory(Map<String, String> opts) {} // 1
+ public ExampleLoggerFactory(Map<String, String> opts) {} // <1>
@Override
public IApimanLogger createLogger(String name) {
- return new ExampleLogger(MyLoggerFactory.getLogger(name)); // 2
+ return new ExampleLogger(MyLoggerFactory.getLogger(name)); // <2>
}
@Override
public IApimanLogger createLogger(Class<?> klazz) {
- return new ExampleLogger(MyLoggerFactory.getLogger(klazz)); // 3
+ return new ExampleLogger(MyLoggerFactory.getLogger(klazz)); // <3>
}
}
----
@@ -376,10 +390,10 @@ public class ExampleLogger implements IDelegateFactory {
}
public void info(String message) {
- logger.message(message); // 1
+ logger.message(message); // <1>
}
- // And many more... 2
+ // And many more... <2>
}
----
<1> Passing the message through to your logger.
@@ -409,7 +423,7 @@ components are available:
|===
-All of the components have asynchronous APIs in order to better support the runtime
+All the components have asynchronous APIs in order to better support the runtime
philosophy in the API Gateway.
TIP: For more information about each component, see its javadoc.
@@ -423,13 +437,15 @@ must also include a Policy Definition JSON file for each policy it is providing.
A plugin definition is a JSON file that must be located within the plugin archive
here:
-```
+[source]
+----
META-INF/apiman/policyDefs
-```
+----
The plugin definition file takes the following form:
-```json
+[source,json]
+----
{
"id" : "policy_name",
"name" : "Policy Name",
@@ -439,7 +455,7 @@ The plugin definition file takes the following form:
"formType" : "JsonSchema",
"form" : "schemas/policy_name.schema"
}
-```
+----
* *id*: The unique id of the policy.
* *name*: The name of the policy.
@@ -449,29 +465,32 @@ The plugin definition file takes the following form:
* *formType*: The type of form to use in the UI when configuring an instance of the policy. See the Policy Configuration section below for details. Valid values: _Default_, _JsonSchema_
* *form*: (_optional_) Path to a UI form that should be used when configuring an instance of the policy. See the Policy Configuration section below for details.
-The most important thing to get right in this file is probably the 'policyImpl'. This
+The most important thing to get right in this file is probably the `policyImpl`. This
is the information that the API Manager will use when it tries to instantiate the
policy implementation at runtime. For policies that come from plugins, the format
-of the 'policyImpl' is:
+of the `policyImpl` is:
-```
+[source]
+----
plugin:{pluginGroupId}:{pluginArtifactId}:{pluginVersion}:{pluginType}/{fullyQualifiedClassname}
-```
+----
An example of what this string might look like if you cracked open a valid apiman plugin
and had a peek at one of its policy definition files is:
-```
+[source]
+----
plugin:io.apiman.plugins:apiman-plugins-example:6.3.3.Final:war/io.apiman.plugins.example.ExamplePolicy
-```
+----
When building your plugin using the recommended maven configuration documented in the
*Using Maven to Create a Plugin* section, it is extremely convenient to simply let
Maven set the values for you:
-```
+[source]
+----
plugin:${project.groupId}:${project.artifactId}:${project.version}:${project.packaging}/com.example.plugins.ExamplePolicy
-```
+----
==== Policy Configuration Form
You may be wondering how configuration information specific to a Plan, API, or
@@ -504,16 +523,18 @@ Alternatively, the policy definition can specify a http://json-schema.org/[JSON
the policy definition JSON file. For example, the policy definition might include the
following:
-```json
+[source,json]
+----
"formType" : "JsonSchema",
"form" : "schemas/policy_name.schema"
-```
+----
In this case, apiman will look for a file inside the plugin artifact in the following location:
-```
+[source]
+----
META-INF/apiman/policyDefs/schemas/policy_name.schema
-```
+----
The file in this location must be a JSON Schema file, which describes the JSON format of the
configuration data expected by the policy implementation. The UI will use this JSON schema
@@ -525,7 +546,8 @@ a plugin, its JSON Schema file, the resulting form displayed in the UI, and the
data format that will be passed to the policy implementation at runtime.
.META-INF/apiman/policyDefs/my-policy.json
-```json
+[source,json]
+----
{
"id" : "my-policy",
"name" : "My First Policy",
@@ -541,7 +563,7 @@ data format that will be passed to the policy implementation at runtime.
],
"form" : "schemas/config-policyDef.schema"
}
-```
+----
TIP: The templates 'language' field will support other languages in future, but
for now is null (i.e. single-language only). The template field itself is
@@ -549,7 +571,8 @@ https://github.com/mvel/mvel[MVEL] (Orb tag syntax), and displays in the UI
after a plugin has been selected by a user.
.META-INF/apiman/policyDefs/schemas/my-policy.schema
-```json
+[source,json]
+----
{
"title" : "Configure My Policy",
"description" : "Configure all of the necessary properties used by my policy.",
@@ -569,18 +592,19 @@ after a plugin has been selected by a user.
}
}
}
-```
+----
.Generated UI Form
image::plugin-policy-config-1.png[Generated UI Form]
.JSON Configuration Data Format
-```json
+[source,json]
+----
{
"property1" : "USER_DATA_1",
"property2" : "USER_DATA_2"
}
-```
+----
TIP: You can easily consume the JSON configuration data above in your policy implementation
by having your policy implementation Java class extend the `AbstractMappedPolicy` base class
@@ -589,7 +613,8 @@ to hold the JSON configuration data.
First, here is the java bean used to (un)marshal the JSON configuration data.
-```java
+[source,java]
+----
public class MyConfigBean implements Serializable {
private static final long serialVersionUID = 683486516910591477L;
@@ -620,11 +645,12 @@ public class MyConfigBean implements Serializable {
}
}
-```
+----
Now have a look at how to use that class when extending the `AbstractMappedPolicy`.
-```java
+[source,java]
+----
public class MyPolicy extends AbstractMappedPolicy<MyConfigBean> {
/**
@@ -651,7 +677,7 @@ public class MyPolicy extends AbstractMappedPolicy<MyConfigBean> {
}
}
-```
+----
===== JSON Schema Policy Configuration SDK
If you are creating a non-trivial JSON Schema (more than just a couple of simple fields)
@@ -659,9 +685,10 @@ it can be difficult to get it right without a few iterations. For this reason,
created a simple "SDK" to help you create your JSON Schema quickly. The SDK can be found
in the apiman github repository at the following location:
-```
+[source]
+----
manager/ui/war/src/main/sdk/json-schema.html
-```
+----
If you have the apiman source code checked out, you can simply open that file in your browser
and start using it to author a custom JSON Schema.
@@ -689,14 +716,15 @@ The first thing you will need is to include the appropriate maven dependencies i
pom.xml file. There is a single additional dependency that you will need (make sure to import it using
the 'test' maven scope):
-```xml
+[source,xml]
+----
<dependency>
<groupId>io.apiman</groupId>
<artifactId>apiman-test-policies</artifactId>
<version>1.1.2-SNAPSHOT</version>
<scope>test</scope>
</dependency>
-```
+----
==== Create and Annotate a JUnit Test Case
Once you have imported the appropriate dependency, you can go ahead and create a JUnit test case. The
@@ -727,7 +755,8 @@ will throw a PolicyFailureError.
Here is a full example of everything working together:
-```java
+[source,java]
+----
@TestingPolicy(CustomPolicy.class)
public class CustomPolicyTest extends ApimanPolicyTest {
@@ -751,7 +780,7 @@ public class CustomPolicyTest extends ApimanPolicyTest {
}
}
-```
+----
==== Providing a Custom Back-End API Mock
Sometimes the echo API is not sufficient when testing your custom policy. Perhaps the custom policy
@@ -761,8 +790,8 @@ an individual test method with @BackEndApi. If you do this then you must supply
a class that implements the IPolicyTestBackEndApi interface. Here is an example of what this might
look like in a test:
-
-```java
+[source,java]
+----
@TestingPolicy(CustomPolicy.class)
public class CustomPolicyTest extends ApimanPolicyTest {
@@ -779,7 +808,7 @@ public class CustomPolicyTest extends ApimanPolicyTest {
}
}
-```
+----
In this example everything works as it did before, but instead of responding with an Echo Response
the send() method will return with a custom response (as created and returned by the provided custom
@@ -880,7 +909,8 @@ Let's try an example.
By default, apiman stores API Gateway configuration in Elasticsearch. The component responsible
for this is called ESRegistry, and it implements this interface:
-```java
+[source,java]
+----
package io.apiman.gateway.engine;
public interface IRegistry {
@@ -898,14 +928,15 @@ public interface IRegistry {
public void getApi(String organizationId, String apiId, String apiVersion, IAsyncResultHandler<Api> handler);
}
-```
+----
Perhaps you'd rather store the API Gateway configuration information into mongodb instead of
Elasticsearch. Since we don't support a mongodb registry, you would need to implement your own
and contribute it via a plugin. Simple create a new plugin and include in it the following
Java class:
-```java
+[source,java]
+----
package org.example.apiman.plugins;
public class MongoDbRegistry implements IRegistry {
@@ -939,7 +970,7 @@ public class MongoDbRegistry implements IRegistry {
}
}
-```
+----
TIP: While optional, it is often useful to provide a constructor that takes a map of configuration
params. These values comes from the *apiman.properties* and is an arbitrary set of keys/values. It
@@ -951,9 +982,10 @@ that the plugin is available to your server. You can do this by deploying the p
to a maven repository and then making that repository available to apiman by adding its URL to
the following property in *apiman.properties*:
-```
+[source]
+----
apiman.plugins.repositories=http://repository.jboss.org/nexus/content/groups/public/
-```
+----
Simply add your organization's maven repository to that (the value can be a comma separated list of
URLs).
@@ -964,33 +996,36 @@ that is running your server. Obviously you can use "mvn install" to accomplish
Next, simply enable the custom component implementation by updating your *apiman.properties* file
like this (for example):
-```
+[source]
+----
apiman-gateway.registry=plugin:GROUP_ID:ARTIFACT_ID:VERSION/org.example.apiman.plugins.MongoDbRegistry
apiman-gateway.registry.mongo.host=localhost
apiman-gateway.registry.mongo.port=27017
apiman-gateway.registry.mongo.username=sa
apiman-gateway.registry.mongo.password=sa123!
apiman-gateway.registry.mongo.database=apiman
-```
+----
The most important part above is the format for the registry itself. It might look something like
this:
-```
+[source]
+----
apiman-gateway.registry=plugin:org.example.apiman-plugins:plugin-mongodb:1.0.0.Final/org.example.apiman.plugins.MongoDbRegistry
-```
+----
Finally, the set of properties prefixed with "apiman-gateway.registry" will be processed and passed
to your *MongoDbRegistry* class's *Map* constructor if one is provided. The map that is passed to
the constructor will contain the following:
-```
+[source]
+----
mongo.host=localhost
mongo.port=27017
mongo.username=sa
mongo.password=sa123!
mongo.database=apiman
-```
+----
==== Core Component Customization Points
This section lists all/most of the available customization points available within apiman. These represent
@@ -1011,62 +1046,69 @@ all of the core apiman components that can be replaced by custom implementations
====== io.apiman.manager.api.core.INewUserBootstrapper Example Configuration
-```
+[source]
+----
apiman-manager.user-bootstrapper.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooUserBootstrapperImpl
apiman-manager.user-bootstrapper.foo1=value-1
apiman-manager.user-bootstrapper.foo2=value-2
-```
+----
====== io.apiman.manager.api.core.IStorage Example Configuration
-```
+[source]
+----
apiman-manager.storage.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooStorageImpl
apiman-manager.storage.foo1=value-1
apiman-manager.storage.foo2=value-2
-```
+----
====== io.apiman.manager.api.core.IStorageQuery Example Configuration
-```
+[source]
+----
apiman-manager.storage-query.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooStorageQueryImpl
apiman-manager.storage-query.foo1=value-1
apiman-manager.storage-query.foo2=value-2
-```
+----
TIP: If your custom IStorage implementation *also* implements IStorageQuery, then it will be used instead of
trying to create a separate instance of IStorageQuery.
====== io.apiman.manager.api.core.IMetricsAccessor Example Configuration
-```
+[source]
+----
apiman-manager.metrics.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooMetricsAccessorImpl
apiman-manager.metrics.foo1=value-1
apiman-manager.metrics.foo2=value-2
-```
+----
====== io.apiman.manager.api.core.IApiKeyGenerator Example Configuration
-```
+[source]
+----
apiman-manager.api-keys.generator.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooApiKeyGeneratorImpl
apiman-manager.api-keys.generator.foo1=value-1
apiman-manager.api-keys.generator.foo2=value-2
-```
+----
====== io.apiman.common.util.crypt.IDataEncrypter Example Configuration
-```
+[source]
+----
apiman.encrypter.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooDataEncrypter
apiman.encrypter.foo1=value-1
apiman.encrypter.foo2=value-2
-```
+----
====== io.apiman.manager.api.core.IApiCatalog Example Configuration
-```
+[source]
+----
apiman-manager.api-catalog.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooApiCatalogImpl
apiman-manager.api-catalog.foo1=value-1
apiman-manager.api-catalog.foo2=value-2
-```
+----
===== API Gateway Components
@@ -1093,60 +1135,67 @@ apiman-manager.api-catalog.foo2=value-2
====== io.apiman.gateway.engine.IRegistry Example Configuration
-```
+[source]
+----
apiman-gateway.registry=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooRegistryImpl
apiman-gateway.registry.foo1=value-1
-```
+----
====== io.apiman.common.util.crypt.IDataEncrypter Example Configuration
-```
+[source]
+----
apiman.encrypter.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooDataEncrypter
apiman.encrypter.foo1=value-1
apiman.encrypter.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.IConnectorFactory Example Configuration
-```
+[source]
+----
apiman-gateway.connector-factory=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooConnectorFactoryImpl
apiman-gateway.connector-factory.foo1=value-1
apiman-gateway.connector-factory.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.policy.IPolicyFactory Example Configuration
-```
+[source]
+----
apiman-gateway.policy-factory=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooPolicyFactoryImpl
apiman-gateway.policy-factory.foo1=value-1
apiman-gateway.policy-factory.foo2=value-2
-```
+----
*Note*: there is rarely a reason to provide a custom policy factory.
====== io.apiman.gateway.engine.IPolicyFailureWriter Example Configuration
-```
+[source]
+----
apiman-gateway.writers.policy-failure=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooPolicyFailureWriterImpl
apiman-gateway.writers.policy-failure.foo1=value-1
apiman-gateway.writers.policy-failure.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.IPolicyErrorWriter Example Configuration
-```
+[source]
+----
apiman-gateway.writers.error=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooPolicyErrorWriterImpl
apiman-gateway.writers.error.foo1=value-1
apiman-gateway.writers.error.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IBufferFactoryComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IBufferFactoryComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooBufferFactoryComponentImpl
apiman-gateway.components.IBufferFactoryComponent.foo1=value-1
apiman-gateway.components.IBufferFactoryComponent.foo2=value-2
-```
+----
*Note*: typically the buffer factory is specific to the platform. For example, there is a buffer factory
used when the API Gateway is running in EAP or WildFly. There is a different buffer factory used when the
@@ -1154,67 +1203,75 @@ API Gateway is running in vert.x. There is typically not another reason to over
====== io.apiman.gateway.engine.components.ICacheStoreComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.ICacheStoreComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooCacheStoreComponentImpl
apiman-gateway.components.ICacheStoreComponent.foo1=value-1
apiman-gateway.components.ICacheStoreComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IHttpClientComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IHttpClientComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooHttpClientComponentImpl
apiman-gateway.components.IHttpClientComponent.foo1=value-1
apiman-gateway.components.IHttpClientComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IJdbcComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IJdbcComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooJdbcComponentImpl
apiman-gateway.components.IJdbcComponent.foo1=value-1
apiman-gateway.components.IJdbcComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.ILdapComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.ILdapComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooLdapComponentImpl
apiman-gateway.components.ILdapComponent.foo1=value-1
apiman-gateway.components.ILdapComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IPeriodicComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IPeriodicComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooPeriodicComponentImpl
apiman-gateway.components.IPeriodicComponent.foo1=value-1
apiman-gateway.components.IPeriodicComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IPolicyFailureFactoryComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IPolicyFailureFactoryComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooPolicyFailureFactoryComponentImpl
apiman-gateway.components.IPolicyFailureFactoryComponent.foo1=value-1
apiman-gateway.components.IPolicyFailureFactoryComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.IRateLimiterComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.IRateLimiterComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooRateLimiterComponentImpl
apiman-gateway.components.IRateLimiterComponent.foo1=value-1
apiman-gateway.components.IRateLimiterComponent.foo2=value-2
-```
+----
====== io.apiman.gateway.engine.components.ISharedStateComponent Example Configuration
-```
+[source]
+----
apiman-gateway.components.ISharedStateComponent=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.FooSharedStateComponentImpl
apiman-gateway.components.ISharedStateComponent.foo1=value-1
apiman-gateway.components.ISharedStateComponent.foo2=value-2
-```
+----
==== Providing a Custom API Catalog
Apiman allows users to import one or more API (to be managed) from a globally configured API Catalog. This
@@ -1234,7 +1291,8 @@ _apiman.properties_ file.
The interface you must implement is *io.apiman.manager.api.core.IApiCatalog* and looked like this at the
time of this writing:
-```java
+[source,java]
+----
/**
* Represents some sort of catalog of live APIs. This is used to lookup
* APIs to import into apiman.
@@ -1255,12 +1313,13 @@ public interface IApiCatalog {
}
-```
+----
The catalog is simply one method which returns a list of *AvailableApiBean* objects. That class
looks something like this:
-```java
+[source,java]
+----
/**
* A bean modeling an API available in one of the configured API catalogs.
@@ -1286,7 +1345,7 @@ public class AvailableApiBean implements Serializable {
/** SNIPPED ALL GETTERS/SETTERS **/
}
-```
+----
Create an implementation of this interface and include it in a valid apiman plugin.
@@ -1294,11 +1353,12 @@ TIP: See the "Creating a Plugin" section of this guide for more information.
Once the plugin is created with your class inside, configure the catalog in _apiman.properties_ like this:
-```
+[source]
+----
apiman-manager.api-catalog.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.ApiCatalogImpl
apiman-manager.api-catalog.property1=value-1
apiman-manager.api-catalog.property2=value-2
-```
+----
Remember, if your implementation class has a constructor that accepts a Map<String, String>, then apiman
will pass the set of applicable configuration properties it finds in apiman.properties when the class is
@@ -1322,7 +1382,8 @@ In order to provide a custom data encrypter, the interface you must implement is
*io.apiman.common.util.crypt.IDataEncrypter*. This same interface is used in both the API Manager and
the API Gateway. The IDataEncrypter interface looks something like this:
-```java
+[source,java]
+----
/**
* Provides a way to encrypt and decrypt data. This is useful when encrypting sensitive
@@ -1336,7 +1397,7 @@ public interface IDataEncrypter {
}
-```
+----
When creating a custom implementation, all you need to do is provide a Java class which implements
the above interface inside a valid apiman plugin.
@@ -1346,11 +1407,12 @@ TIP: See the "Creating a Plugin" section of this guide for more information.
Once the plugin is created with your class inside, configure the data encrypter in _apiman.properties_ like
this (*note*: it only needs to be configured in a single place for both the Manager and Gateway):
-```
+[source]
+----
apiman.encrypter.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.DataEncrypterImpl
apiman.encrypter.property1=value-1
apiman.encrypter.property2=value-2
-```
+----
Remember, if your implementation class has a constructor that accepts a Map<String, String>, then apiman
will pass the set of applicable configuration properties it finds in apiman.properties when the class is
@@ -1370,13 +1432,14 @@ some installers may prefer a custom format for these. This can be accomplished
implementation of *io.apiman.gateway.engine.IPolicyFailureWriter* and/or a custom implementation of
*io.apiman.gateway.engine.IPolicyErrorWriter*.
-```java
+[source,java]
+----
public interface IPolicyFailureWriter {
public void write(ApiRequest request, PolicyFailure failure, IApiClientResponse response);
}
-```
+----
```java
public interface IPolicyErrorWriter {
@@ -1396,17 +1459,19 @@ TIP: See the "Creating a Plugin" section of this guide for more information.
Once the plugin is created with your class inside, configure either the failure writer, the error
writer, or both in _apiman.properties_ like this:
-```
+[source]
+----
apiman-gateway.writers.policy-failure=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.PolicyFailureWriterImpl
apiman-gateway.writers.policy-failure.property1=value-1
apiman-gateway.writers.policy-failure.property2=value-2
-```
+----
-```
+[source]
+----
apiman-gateway.writers.error=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.PolicyErrorWriterImpl
apiman-gateway.writers.error.property1=value-1
apiman-gateway.writers.error.property2=value-2
-```
+----
Remember, if your implementation class has a constructor that accepts a Map<String, String>, then apiman
will pass the set of applicable configuration properties it finds in apiman.properties when the class is
@@ -1428,7 +1493,8 @@ bootstrapping tasks when a new user is created, for example:
This can be done by providing your own custom implementation of *io.apiman.manager.api.core.INewUserBootstrapper*:
-```java
+[source,java]
+----
/**
* This class is used to bootstrap new users. This bootstrapper is used
* whenever a new user logs into the API Manager UI for the first time.
@@ -1441,7 +1507,7 @@ public interface INewUserBootstrapper {
public void bootstrapUser(UserBean user, IStorage storage) throws StorageException;
}
-```
+----
When invoked, the boostrap method is given the *UserBean* of the user being created as well as the
storage object. The storage object can be used to create additional entities for the user, such as
@@ -1455,11 +1521,12 @@ TIP: See the "Creating a Plugin" section of this guide for more information.
Once the plugin is created with your class inside, configure the user bootstrapper in in _apiman.properties_
like this:
-```
+[source]
+----
apiman-manager.user-bootstrapper.type=plugin:com.example.groupId:artifactId:1.0.Final/com.example.apiman.UserBootstrapperImpl
apiman-manager.user-bootstrapper.property1=value-1
apiman-manager.user-bootstrapper.property2=value-2
-```
+----
Remember, if your implementation class has a constructor that accepts a Map<String, String>, then apiman
will pass the set of applicable configuration properties it finds in apiman.properties when the class is

docs(dev-guide): fix callouts and use Asciidoc-style code blocks