Peapod maps your TinkerPop 3 graph onto a rich Java domain model. Peapod is developed as an alternative to Frames in TinkerPop 2.
Disclaimer: version latest is still an experimental release using Apache Tinkerpop 3.1.1-incubating.
You start by specifying your graph structure through abstract classes, enriched with Peapod annotations. Peapod will then generate at compile-time all the necessary implementation classes, attempting to reduce boilerplate code for basic graph access and traversals.
Peapod favors convention over configuration and therefore is simpler to use than TinkerPop 2 Frames
Example:
@Vertex public abstract class Person { // vertex example with abstract class public abstract String getName(); public abstract List<Created> getCreated(); } @Edge public abstract class Created { public abstract Float getWeight(); @In public abstract Software getSoftware(); } @Vertex public interface Software { // vertex example with interface public abstract String getName(); }
Starting from a FramedGraph
instance, you can query and manipulate the TinkerPop 3 graph. All reads and writes are immediately propagated to the wrapped TinkerPop 3 elements.
Graph g = TinkerGraph.open(); FramedGraph graph = new FramedGraph(g, Package.getPackage("com.company.application.model")); Person person = graph.addVertex(1, Person.class); person.setName("alice"); List<Person> result = graph.V(Person.class).has("name", "alice").toList(); assertEquals(1, result.size());
Peapod is designed to have minimal overhead because code generation happens at compile time using Java annotation processors and reflection is limited to the absolute minimum only at startup time. The generated source code is transparent can be easily debugged.
Traversals in Peapod latest are still basic. The future goal is to have more advanced traversals using the DSL framework in TinkerPop 3. Because the graph structure is defined by the framing classes, Peapod could generate these complex traversal classes easily.
Define your domain model using annotated anonymous classes. Peapod will generate TinkerPop 3-compliant source code to traverse and manipulate your graph.
Create an abstract class or interface and annotate with @peapod.annotations.Vertex
.
@Vertex public abstract class Person {}
@Vertex public interface Person {}
The class simple name will act as vertex label. You can alter this by setting the annotation value.
@Vertex("individual") public abstract class Person {}
Next, define a list of vertex properties using abstract JavaBean setter and getter methods.
@Vertex public abstract class Person { public abstract String getName(); public abstract void setName(String name); }
The JavaBean property name will be used as vertex property name. The property name can be altered by adding the @peapod.annotations.Property
annotation to any of the JavaBean methods.
@Vertex public abstract class Person { @Property("name") public abstract String getLastName(); public abstract void setLastName(String lastName); }
For multi-properties you can also use adder and remover methods. Peapod recognizes singular and pluralized property names as belonging to the same property group.
@Vertex public abstract class Person { public abstract List<String> getNames(); public abstract void addName(String name); public abstract void removeName(String name); }
In a similar way, you can frame TinkerPop 3 edges using abstract classes or interfaces. The class simple name in lowercase will act as the edge label. Add any edge properties and specify at most the two adjacent vertices by using the @In
and @Out
annotations.
@Edge public abstract class Created { public abstract Float getWeight(); @Out public abstract Person getPerson(); @In public abstract Software getSoftware(); }
Next, you can integrate the framed edge class in the corresponding vertex classes. The direction is by default outgoing.
@Vertex public abstract class Person { public abstract List<Created> getCreated(); public abstract Created addCreated(Software software); public abstract Created removeCreated(Software software); }
If you don't need to explicitely frame the edge, you can also create direct relationships between vertices and annotate the method with @Edge
. By default the JavaBean property name acts as edge label, but this can be overridden by setting the annotation value
@Vertex public abstract class Person { @Edge("created") public abstract List<Software> getSoftware(); public abstract void addSoftware(Software software); public abstract void removeSoftware(Software software); }
Attention: at this moment, only getter methods can change the default direction (outgoing) by adding @In
or @Both
annotations. These annotations are ignored on setter, adder and remover methods.
@Vertex public abstract class Person { @In @Edge("knows") public abstract List<Person> getKnownBy(); }
Peapod supports meta-properties which is a new feature of TinkerPop 3. You simply define a framing class for the vertex property and add properties which will be mapped onto meta-properties.
You must obligatory implement the FramedVertexProperty
interface in order to specify the vertex property type. FramedVertexProperty
defines a T getValue()
and void setValue(T)
method to alter the property value.
@VertexProperty public abstract class Name implements FramedVertexProperty<String> { public abstract String getAcl(); public abstract void setAcl(String acl); }
Once the vertex property class is defined you can add it to a @Vertex
class.
@Vertex public abstract class Person { public abstract List<Name> getNames(); public abstract Name getName(String name); public abstract Name addName(String name); public abstract void removeName(String name); }
Peaopod supports the @javax.annotation.PostConstruct
annotation to initialize vertices when added to the framed graph.
@Vertex public abstract class Person { public abstract Date getCreationTms(); public abstract void setCreationTms(Date date); @PostConstruct protected void init() { setCreationTms(new Date()); } } Person person = graph.addVertex(Person.class); assertTrue(person.getCreationTms() != null);
The framed graph wraps a TinkerPop 3 Graph
and delegates all queries and graph manipulations to the underlying graph. FramedGraph
must be initialized with a base package. Peapod will recursively scan the provided package and search for framing classes annotated with @Vertex
, @VertexProperty
or @Edge
.
Graph g = TinkerGraph.open(); FramedGraph graph = new FramedGraph(g, Package.getPackage("com.company.application.model"));
You create new vertices by specifying the framing class and an optional identifier if the TinkerPop 3 graph database supports it.
Person person = graph.addVertex(1, Person.class); person.setName("alice");
You can retrieve a graph vertex by id. Peapod will infer the framing class from the vertex label.
Person person = graph.v(1); assertEquals("alice", person.getName());
When the vertices in the graph don't define a label, you can still provide a framing class yourself.
Person person = graph.v(1, Person.class); assertEquals("alice", person.getName());
You can query and navigate the graph starting from the framed graph and a framing class.
List<Person> result = graph.V(Person.class).has("name", "alice").toList(); assertEquals(1, result.size());
Traversals in Peapod latest are still very basic. The future goal is to generate more advanced traversal classes using the DSL framework in TinkerPop 3. Because the graph structure is defined by the framing classes, Peapod would be able to define these traversal classes easily and save you from writing a lot of unnecessary boilerplate code.
Vertices can optionally implement the FramedVertex
interface which defines a serie of traversal methods.
@Vertex public abstract class Person FramedVertex<Person> { @Edge("knows") public abstract List<Person> getKnowsPerson(); public List<Person> getKnowsPersonsOlderThan(int age) { return out("knows", Person.class).has("age", Compare.gt, age).toList(); } } assertThat(marko.getKnowsPersonsOlderThan(30), contains(josh));
The source code to Peapod, its samples, and this website is available on GitHub.
<dependency> <groupId>org.bayofmany.peapod</groupId> <artifactId>peapod</artifactId> <version>latest</version> </dependency>
Peapod requires at minimum Java 8.
Copyright 2015 Bay of Many. Licensed 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.
Thanks to all the exceptional TinkerPop 3 talents for creating this amazing Open Source Graph Computing Framework.
Thanks to GitHub for providing the GIT repository.
Thanks to Cloudbees for providing the Jenkins build infrastructure.
Thanks to Sonatype for hosting Peapod in the central maven repository.
Thanks to EJ Technologies for providing a JProfiler license, the Award-Winning All-in-One Java Profiler.