syncleus / ferma Goto Github PK
View Code? Open in Web Editor NEWAn ORM / OGM for the TinkerPop graph stack.
Home Page: http://syncleus.com/Ferma
License: Apache License 2.0
An ORM / OGM for the TinkerPop graph stack.
Home Page: http://syncleus.com/Ferma
License: Apache License 2.0
In reflections
version 0.9.12
there is a bug which may indirectly be a problem when Ferma is used with JanusGraph.
Here in JanusGraph we retrieve PreInitializeConfigOptions
even if there is no scanUrls.
https://github.com/JanusGraph/janusgraph/blob/677a57aa985a7ea47af70d0eaba30171d765c79d/janusgraph-core/src/main/java/org/janusgraph/core/util/ReflectiveConfigOptionLoader.java#L248
This works fine till reflections version 0.9.12
which introduces the next bug: ronmamo/reflections#273
The thing is that the method getTypesAnnotatedWith
should return empty collection but instead it breaks existing contract and returns a wrong exception.
I think, it would be good to downgrade reflections
to 0.9.11
till the bug isn't fixed. After that, it would be better to avoid 0.9.12
version and upgrade directly to the version where it is fixed (i.e. 0.9.13
or later).
The error "The Client driver version is different than Server version: client=37, server=36. You could not use the full features of the newer version. Assure to have the same versions on both" comes up.
Can i use the client of version=36 in ferma 3?
I've got a bug with fields which are mandatory for classes.
I'm trying to create an Edge on an existing vertex using
edgeHasCalculs= COP_Vertex.addEdgeToExistingVStoreLocation(storeVertex, calculs.INITIALIZER_EHasCalculs);
edgeHasCalculs.setTypeCalcul(classOf[VCOP].getSimpleName);
edgeHasCalculs.setTimespan(timespan);
edgeHasCalculs.setEnd_Date(endDate.toDate());
It fails at the first line, because of :
"The field 'EHasCalculs.Timespan' is mandatory, but not found on record: EHasCalculs{out:#-1:-2,in:#21:2}"
I would need to be able to specify the keyValues on creation of the baseEdge so that when it goes in the delegatingFrameGraph, the classInitializer or an other way be able to specify keyValues in this function.
public <T> T addFramedEdge(final VertexFrame source, final VertexFrame destination, final String label, final ClassInitializer<T> initializer, final Object... keyValues) {
final Edge baseEdge = source.getElement().addEdge(label, destination.getElement(), keyValues);
final T framedEdge = frameNewElement(baseEdge, initializer);
return framedEdge;
}
I'm using the annotation methods:
@Incidence(label = "EHasCalculs", direction = Direction.OUT)
public abstract <E extends AbstractEdgeFrame> E addEdgeToExistingVStoreLocation(VStoreLocation son, ClassInitializer<? extends E> edgeInitializer);
Thanks
There are a few exceptions for which we could improve the message to be more useful. Consider the following ticket as an example: #12
Create a Ferma-examples project including various usage examples. There should be a collection of very simple hello-world example projects showing off all of Ferma's features. There should also be an example project for each major graph DB and how Ferma can work with it. Ideally these should run in-memory through maven but when this isnt possible perhaps throw in some vagrant images as well.
On the Ferma hosted documentation/page several versions are missing from the javadoc links.
I'm just trying to use Ferma now (together with OrientDB), and I'm trying to find a way to sort through a result. I think there's a way using the .traverse() method, but the documentation doesn't seem to have almost any examples or information for such a thing.
How can I do that?
[HELP WANTED]
Amazon's graph db "Neptune" is now available. I'm looking to use Ferma as an OGM for an upcoming project. Amazon says Neptune supports Property Graphs by way of Apache TinkerPop. Does that mean by proxy Ferma will work with Neptune? I don't see it listed as an officially support graph db. If not what would it take to add support for it?
Is there a way to change the vertex label "vertex" to an own String? I looked into the API but all I found was how to change the label for an edge.
Labels are a integral part of tinkerpop graphs, with the option to add vertexes with g.addV(label)
.
With this issue I am asking on input on ways to make it a more integral part in this project. In the text below I go over why it is that I would like to see it added. The current way of doing it and some possible solutions to implement it.
Labels are used to distinguish between vertexes. While it is not needed for Ferma as you can use the class structure to distinguish between vertexes, it would be nice to have a easy way to set them so that programs that rely on the graph output can use these.
Currently you have to do it with framedGraph.addFramedVertex(new DefaultClassInitializer<>(className), T.label, labelName);
and the recetlly added (#56) framedGraph.addFramedVertex(className, T.label, labelName);
I have made an attempt to have a better way to add these with annotations on the vertex class as labels are generally used to distinguish between types of nodes. This one is visible in a pull request on my own repo. But I am not yet convinced that this is the way to go. (this implementation is just a proof of concept and still needs a bit of work. Like checking if no label is given as argument when adding the vertex)
Some other ways that i have thought of was to add the function framedGraph.addV(className, labelName);
To more closely mirror the Tinkerpop implementation.
The last options would be a breaking change that would split the current @GraphElement
into two separate annotations, one being @GraphVertex
and the other @GraphEdge
, where GraphVertex has a optional label.
I would love to hear thoughts on this subject as I have to use labels in a project that I am currently working on. I therefore also have some time to spare to implement this into this library.
When a set operation is performed on an adjacency it always drops all existing edges then recreates them. However if the vertex in a set operation are already adjacencies those edges should be preserved.
Right now, this relies on the context classloader, but I would like to provide my own implementation for use by ByteBuddy.
I am curious if it would be possible to have a Spring Data integration of all the Gremlin graph databases - something like: https://github.com/gjrwebber/spring-data-gremlin but using Tinkerpop 3+. I was expecting a less verbose annotation style without the need to create new classes (framed vertices/edges) like it is done with neo4j ogm: https://github.com/neo4j/neo4j-ogm. It would be nice if spring-data-gremlin is merged in spring projects like neo4j one: https://github.com/spring-projects/spring-data-neo4j
I am also curious if Datastax DSE Graph could be supported out of the box from Ferma.
Thanks!
Hi guys,
is there any plans on support annotations (e.g. @Property) at the member variable instead of getter/setters (similar to JPA)? This would provide a much better overall experience in Java as well as Kotlin.
Thanks,
In order to register a custom Annotation, it is necessary to create an annotation method handler and add it to the AnnotationFrameFactory's methodHandlers map.
The issue is that AnnotationFrameFactory's methodHandlers is private, hence it is not accessible.
Changing it to "protected" it allows to extend AnnotationFrameFactory and add the custom annotation handler right inside the constructor.
We need to start preparing Ferma to use Tinkerpop v3 as the backend. If we can get someone to update the code in a new branch to be fully compatible with the Tinkerpop v3 release, and all the unit tests passing we should be golden!
I am using Ferma with JanusGraph. JanusGraph allows to set a label to a vertex. It would be awesome if Ferma could assign labels to vertices. Right now Ferma always assigns vertex
label to all vertices.
I notice in com.syncleus.ferma.framefactories.DefaultFrameFactory
, it calls kind.newInstance()
which is deprecated since Java 9.
Also, the message "Could not instantiate kind: " + kind.getName() wasn't that helpful in establishing that the framework is looking for a default no-args constructor.
Hi,
just wanted to take a quick look into Ferma and discovered the first issue. In AdjacencyMethodHandler.java, line 411 and 441 there is no 'break' so when using Direction.OUT an IllegalStateException is always thrown.
Best regards,
René
Hi guys, what is the status of this project? Is this something that is still living? thanks
Used method:
<T> T addFramedEdge(final VertexFrame source, final VertexFrame destination, final String label, Class<T> kind);
Version: 2.1.0-SNAPSHOT
I will take a look at this when i find the time and add a testcase that reproduces this problem.
we no longer use gerrit, remove .gitreview.
Hello guys.
I have found some unexpected behaviour of using framed graph.
Let's assume we have 2 classes A
and B
. Each of them have the same property name
.
In the graph are two objects: object A
with name
= a
, and object B
with name = b
.
But if I am trying to traverse over graph to grab object with name
= b
and get object of kind A
using method next... I am getting object A
.
Here is code:
package ferma;
import com.syncleus.ferma.AbstractVertexFrame;
import com.syncleus.ferma.DelegatingFramedGraph;
import com.syncleus.ferma.FramedGraph;
import com.syncleus.ferma.annotations.Property;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class RowTest {
public static abstract class Person extends AbstractVertexFrame {
@Property("name")
public abstract String getName();
@Property("name")
public abstract void setName(String name);
}
public static abstract class Animal extends AbstractVertexFrame {
@Property("name")
public abstract String getName();
@Property("name")
public abstract void setName(String name);
@Property("kind")
public abstract String getKind();
@Property("kind")
public abstract void setKind(String kind);
}
@Test
public void name() {
Set<Class<? extends AbstractVertexFrame>> types = new HashSet<>(Arrays.asList(
Person.class,
Animal.class
));
Graph graph = TinkerGraph.open();
FramedGraph fg = new DelegatingFramedGraph<>(graph, true, types);
Person person = fg.addFramedVertex(Person.class);
String jeff = "Jeff";
person.setName(jeff);
Animal animal = fg.addFramedVertex(Animal.class);
animal.setKind("dog");
String lessi = "lessi";
animal.setName(lessi);
Person personLessi = fg.traverse(input -> input.V().has("name", lessi)).next(Person.class);
Assert.assertEquals(personLessi.getName(), lessi);
System.out.println(personLessi.getClass());
System.out.println(personLessi);
}
}
// Result:
// class ferma.RowTest$Person$ByteBuddy$0BUlWIhG
// {
// "id": 3,
// "elementClass": "vertex",
// "ferma_type": "ferma.RowTest$Animal",
// "kind": "dog",
// "name": "lessi"
// }
Is it expected behavior? I did not found any information about this in the documentation.
I am using ferma version 3.2.1
TinkerPop supports re-attaching DetachedElement back to graph. It's possible to achieve something similar using ferma ?
We using ferma in rest api so user can get some graph elements, modify them and send back so we need to update our graph element. Currently do doing it manually but possibility to re-attaching elements to graph can be very useful.
A basic vertex creation in Ferma 3.0.2 generates a ClassCastException:
java.lang.ClassCastException: com.syncleus.ferma.annotations.FermaTest$Employee$ByteBuddy$Yxytgyif cannot be cast to com.syncleus.ferma.AbstractElementFrame
at com.syncleus.ferma.DelegatingFramedGraph.frameElement(DelegatingFramedGraph.java:243)
at com.syncleus.ferma.DelegatingFramedGraph.frameNewElement(DelegatingFramedGraph.java:249)
at com.syncleus.ferma.DelegatingFramedGraph.addFramedVertex(DelegatingFramedGraph.java:313)
at com.syncleus.ferma.DelegatingFramedGraph.addFramedVertex(DelegatingFramedGraph.java:319)
at com.syncleus.ferma.annotations.FermaTest.testCreation(FermaTest.java:54)
This is the test class. The cause is not the inner class because it doesn't work as seperate class either.
public class FermaTest {
public static abstract class Employee implements VertexFrame {
@Property("name")
public abstract String getName();
@Property("name")
public abstract void setName(String name);
}
@Test
public void testCreation() {
Set<Class<?>> types = new HashSet<>(Arrays.asList(new Class<?>[]{Employee.class}));
Graph g = TinkerGraph.open();
//implies annotated mode
FramedGraph fg = new DelegatingFramedGraph(g, true, types);
Employee e1 = fg.addFramedVertex(Employee.class);
e1.setName("Jeff");
}
}
OrientDB's transaction handling requires some workarounds to be applied in order to be used in combination with Ferma.
I created my own vertex frame which internally deals with some of those requirements:
public class OrientVertexFrame extends AbstractVertexFrame {
private Object id;
// ThreadLocal which will hold the base element reference for each thread and
// reload the element if required.
public ThreadLocal<Element> threadLocalElement = ThreadLocal.withInitial(() -> ((WrappedVertex)getGraph().getVertex(id)).getBaseElement());
// ThreadLocal which will hold the current active graph (eg.: Transaction)
public static ThreadLocal<FramedGraph> threadLocalGraph = new ThreadLocal<>();
@Override
protected void init(FramedGraph graph, Element element) {
super.init(graph, element);
this.id = element.getId();
}
@Override
public Vertex getElement() {
Element vertex = threadLocalElement.get();
// Unwrap wrapped vertices
if (vertex instanceof WrappedElement) {
vertex = (Vertex) ((WrappedElement) vertex).getBaseElement();
}
return (Vertex)vertex;
}
@Override
public FramedGraph getGraph() {
return new DelegatingFramedGraph<>(threadLocalGraph.get(), true, false);
}
}
Transactions should set the thread local and restore it within the duration of the transaction. I created an autoclosable which handles those transactions and updates to the threadlocal.
Based upon this conversation, this is the preferred way to create vertices and modify properties:
https://groups.google.com/forum/#!topic/gremlin-users/NFf9gJasjb8
Not doing this means that "EventStrategy" cannot be used effectively in conjunction with Ferma.
In the Node.java
reproduced below, using Ferma 3.0.2 and tinkergraph-gremlin 3.2.3 on OpenJDK 8u121-b13, attempting to use Node.traverse() with an anonymous traversal (__.out("parent")
) results in the following compile-time error (change the call to traverse1()
back to traverse()
first):
Node.java:[56,46] error: incompatible types: no instance(s) of type variable(s) A exist so that GraphTraversal<A,Vertex> conforms to Traversal<?,CAP#1>
Changing the argument type of traverse()
from Function<GraphTraversal<? extends Vertex, ? extends Vertex>, GraphTraversal<?, ?>>
to Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>>
seems to correct the issue. Following the types through the current TinkerPop API, input.V(getElement().id())
returns type GraphTraversal<Vertex, Vertex>
so I believe it is sufficient to require traverser
to have type Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>>
.
I imagine a similar issue exists with AbstractEdgeFrame
.
Node.java:
package com.syncleus.ferma.issues;
import com.syncleus.ferma.AbstractVertexFrame;
import com.syncleus.ferma.DelegatingFramedGraph;
import com.syncleus.ferma.FramedGraph;
import com.syncleus.ferma.Traversable;
import com.syncleus.ferma.annotations.Adjacency;
import com.syncleus.ferma.annotations.Property;
import javax.annotation.Nullable;
import java.util.function.Function;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
public abstract class Node extends AbstractVertexFrame {
public static void main(String[] args) {
// create new graph
Graph graph = TinkerGraph.open();
FramedGraph fg = new DelegatingFramedGraph(graph, true, true);
// add five nodes (vertices)
Node[] nodes = new Node[5];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = fg.addFramedVertex(Node.class);
nodes[i].setName("Node" + i);
}
// Node0 <- Node1 <- ... <- Node4
for (int i = 1; i < nodes.length; i++) {
nodes[i].setParent(nodes[i - 1]);
}
// ask Node3 for its grandparent (Node1)
System.out.println(nodes[3].getGrandParent());
}
@Property("name")
public abstract String getName();
@Property("name")
public abstract void setName(String name);
@Adjacency(label = "parent", direction = Direction.OUT)
public abstract Node getParent();
public void setParent(Node parent) {
// node can only have one parent
setLinkOut(parent, "parent");
}
public Node getGrandParent() {
// with traverse(): Node.java:[55,46] error: incompatible types: no instance(s) of type variable(s) A exist so that GraphTraversal<A,Vertex> conforms to Traversal<?,CAP#1>
return traverse1((v) -> v.repeat(__.out("parent")).times(2)).next(Node.class);
}
public <T extends Traversable<?, ?>> T traverse1(final Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>> traverser) {
return this.getGraph().traverse(new Function<GraphTraversalSource, GraphTraversal<?, ?>>() {
@Nullable
@Override
public GraphTraversal<?, ?> apply(@Nullable final GraphTraversalSource input) {
return traverser.apply(input.V(getElement().id()));
}
});
}
}
When converting from Frames to Ferma, I found this issue.
Why DelegatingFramedGraph
doesn't implement getVertex(Object id, Class Type)
?
Would it be possible to extend the GraphElement annotation to take in a String value (default "") that can be used to define a label of the Element/Edge/Vertex being created. If blank the simple class name could be used as a fallback.
The checklist currently used in the CONTRIBUTING.md file was pulled over from another project. While it is mostly accurate it should be updated to be specific to Ferma.
Specifically this section could be improved upon:
* Make sure any references to the version number in the readme is updated
* Version number in dependency maven snippet.
* Add new version to javadoc version list.
update license header to new year.
I am trying to use ferma ORM for my project . Current problem is, I am not able to persist my entities to JanusGraph DB.
Here is my code Required :
Entity Class
public abstract class Person extends AbstractVertexFrame {
private String id;
private String name;
private int age;
private String mobile;
@Property("age")
public abstract int getAge();
@Property("age")
public abstract void setAge(int age) ;
@Property("mobile")
public abstract String getMobile();
@Property("mobile")
public abstract void setMobile(String mobile) ;
public String getId() {
return id;
}
@Property("name")
public abstract String getName() ;
@Property("name")
public abstract void setName(String name);
public String toString(){
return this.name+" has Id"+this.getId();
}
}
This is how I create/initialize my DelegatedFramedGraph bean:
@Bean
FramedGraph framedGraph(JanusGraph graph,GremlinBeanPostProcessor gremlinBeanPostProcessor){
return new DelegatingFramedGraph(graph,true,gremlinBeanPostProcessor.getEntityClasses());
}
JanusGraph is initialized :
@Bean
JanusGraph graph(JanusGremlinGraphFactory janusGremlinGraphFactory){
JanusGraph janusGraph = null;
janusGraph = janusGremlinGraphFactory.openGraph();
return janusGraph;
}
@Bean
JanusGremlinGraphFactory janusGremlinGraphFactory(){
JanusGremlinGraphFactory jggf;
jggf = new JanusGremlinGraphFactory();
jggf.setConfiguration(getConfiguration());
return jggf;
}
When I try to persist it:
@Autowired
private FramedGraph framedGraph;
public String savePerson(String name,int age,String mobile){
Person person = framedGraph.addFramedVertex(Person.class);
person.setName(name);
person.setAge(age);
person.setMobile(mobile);
System.out.println(person.getName()+"and person id is"+person.getId());
return person.toString();
}
Nothing is stored to JanusGraph, not sure where is the problem.
Can somebody help me ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.