-
Notifications
You must be signed in to change notification settings - Fork 116
Extension Points
Extension points refer to the places from which Rexster can be extended and are defined by the @ExtensionDefinition
annotation which has an extensionPoint
parameter. This parameter must be defined on any method to be exposed as an extension on Rexster. The value of the extensionPoint
parameter is a selection from the ExtensionPoint
enumeration. The following extension point options are available:
extension point | uri extends from |
---|---|
GRAPH | http://{base}/{graph} |
EDGE | http://{base}/{graph}/edges/{id] |
VERTEX | http://{base}/{graph}/vertices/{id} |
By default, the @ExtensionDefinition
assumes that the ExtensionResponse
will return an entity of type application/json
. To override that value, simply supply the revised mime-type to the produces
parameter, as in:
@ExtensionDefinition(extensionPoint = ExtensionPoint.VERTEX, produces = MediaType.APPLICATION_XML)
public ExtensionResponse doVertexToXml(@RexsterContext Vertex vertex) {
String xml = "<vertex><id>" + vertex.getId().toString() + "</id></vertex>";
return new ExtensionResponse(Response.ok(xml).build());
}
The code above is taken from the ProducesXmlExtension
in the Sample Kibbles project.
When the extension method produces JSON, Rexster tries to add some standard attributes to the response. It will look to add the version
and queryTime
as in:
{
"some-key":"some-value",
"other-key":"other-value",
"version":"0.3-SNAPSHOT",
"queryTime":24.940088
}
To override this default behavior, Rexster can be instructed to not add these values to JSON responses by setting the tryIncludeRexsterAttributes
on the ExtensionDefinition
to false
. As stated earlier, this value is true
by default. In the event that the produces
value is set to something other than application/json
, Rexster will behave as though the value of tryIncludeRexsterAttributes
is false
.
There are multiple types of extensions. The type of extension is driven by a combination of the settings in the ExtensionDefinition
.
type | defined by |
---|---|
Root | An ExtensionDefinition defined with an ExtensionPoint of GRAPH , VERTEX or EDGE with no path. |
Path | An ExtensionDefinition defined with an ExtensionPoint of GRAPH , VERTEX or EDGE and a specified path. |
Consider the following code snippet from the SimpleRootExtension
extension class in the Sample Kibbles project:
ExtensionNaming(name = SimpleRootExtension.EXTENSION_NAME, namespace = SimpleRootExtension.EXTENSION_NAMESPACE)
public class SimpleRootExtension extends AbstractRexsterExtension {
public static final String EXTENSION_NAME = "simple-root";
public static final String EXTENSION_NAMESPACE = "tp";
@ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH)
public ExtensionResponse doWorkOnGraph(@RexsterContext Graph graph) {
return toStringIt(graph);
}
}
will serve at:
http://{base}/{graph}/tp/simple-root
When defining an ExtensionDefinition
in this way, it is referred to as a “root extension” where the extension serves from the root of the ExtensionPoint
. A single root extension can be defined for a single extension point within a namespace and extension class. Therefore, the following extension would not be valid:
ExtensionNaming(name = SimpleRootExtension.EXTENSION_NAME, namespace = SimpleRootExtension.EXTENSION_NAMESPACE)
public class SimpleRootExtension extends AbstractRexsterExtension {
public static final String EXTENSION_NAME = "simple-root";
public static final String EXTENSION_NAMESPACE = "tp";
@ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH)
public ExtensionResponse doWorkOnGraph(@RexsterContext Graph graph) {
return toStringIt(graph);
}
@ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH)
public ExtensionResponse doWorkSomeNonsenseWorkOnGraph(@RexsterContext Graph graph) {
// DON'T INCLUDE TWO METHODS THAT EXTEND FROM THE SAME EXTENSIONPOINT
// UNLESS SPECIFYING A PATH EXTENSION (described below)
return toStringIt(graph.getVertex(1));
}
}
While Rexster does not complain if it comes across the above scenario, it may not behave as expected. Rexster will simply choose the first and best method match to the request.
In addition to root extensions, there are also path extensions. Path extensions allow an extension to have multiple service methods exposed from the same namespace, extension name and extension point. Consider the following code snippet from the SimplePathExtension
extension class in Sample Kibbles project:
@ExtensionNaming(name = SimplePathExtension.EXTENSION_NAME, namespace = SimplePathExtension.EXTENSION_NAMESPACE)
public class SimplePathExtension extends AbstractRexsterExtension {
public static final String EXTENSION_NAME = "simple-path";
public static final String EXTENSION_NAMESPACE = "tp";
@ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "some-work")
public ExtensionResponse doSomeWorkOnGraph(@RexsterContext Graph graph) {
return toStringIt(graph, "some");
}
@ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "other-work")
public ExtensionResponse doOtherWorkOnGraph(@RexsterContext Graph graph){
return toStringIt(graph, "other");
}
}
Note that there are two ExtensionDefinition
annotations on two different methods that both specify the ExtensionPoint.GRAPH
. It was previously established in the root extension section that this specification is not permitted, however, the difference here is the usage of the path
parameter on the annotation. The value of the path
parameter helps to identify the method to be exposed on the extension, such that Rexster will serve those methods on the following URIs:
http://{base}/{graph}/tp/simple-path/some-work
http://{base}/{graph}/tp/simple-path/other-work
Like the root extension, the path extension will behave inconsistenly if there is more than one method on the extension that has the same namespace, extension name, extension point and path. Rexster will always serve the first method to match the request.