1

I'm receiving the following error while using the @GremlinGroovy annotation associated with tinkerpop's frames.

java.lang.ClassCastException: com.thinkaurelius.titan.graphdb.relations.CacheEdge cannot be cast to com.tinkerpop.blueprints.Vertex
    at com.tinkerpop.frames.structures.FramedVertexIterable$1.next(FramedVertexIterable.java:36)
    at com.tinkerpop.frames.annotations.gremlin.GremlinGroovyAnnotationHandler.processVertex(GremlinGroovyAnnotationHandler.java:75)
    at com.tinkerpop.frames.annotations.gremlin.GremlinGroovyAnnotationHandler.processElement(GremlinGroovyAnnotationHandler.java:114)
    at com.tinkerpop.frames.annotations.gremlin.GremlinGroovyAnnotationHandler.processElement(GremlinGroovyAnnotationHandler.java:30)
    at com.tinkerpop.frames.FramedElement.invoke(FramedElement.java:83)
    at com.sun.proxy.$Proxy81.getProxyCandidateEdgeFromPersonUuid(Unknown Source)
    at com.company.prod.domain.Person$Impl.toImpl(Person.java:100)
    ....

The following line causes the error:

FooEdge fe = foo.getFooEdgeFromUuid(this.getUuid());

Which is calling this method:

@GremlinGroovy("it.outE('has').filter{it.inV().has('uuid', T.eq, uuid).hasNext()}")
FooEdge getFooEdgeFromUuid(@GremlinParam("uuid") String uuid);

I've also tried the following traversal (which causes the same error):

@GremlinGroovy("it.out('has').has('uuid', T.eq, uuid).inE('has')")

However, when I open a gremlin shell to test out the same exact traversal - everything works out just fine. Any thoughts on what may be causing the issue?

cscan
  • 3,684
  • 9
  • 45
  • 83

2 Answers2

0

This isn't as much of an answer as it is to a workaround. Instead of using the @GremlinGroovy annotation one can use gremlin with the @JavaHandler annotation.

@JavaHandler
void getFooEdgeFromUuid(String uuid);

abstract class Impl implements JavaHandlerContext<Vertex>, Foo {
    public FooEdge getFooEdgeFromUuid(String uuid) {
        return frameEdges(
                gremlin().out("has")
                        .has("person-uuid", Tokens.T.eq, uuid)
                        .inE("has"),
                FooEdge.class).iterator().next();
    }
}
cscan
  • 3,684
  • 9
  • 45
  • 83
0

I don't think you have proper usage there give the documentation on Frames for that annotation:

https://github.com/tinkerpop/frames/wiki/Gremlin-Groovy

First, note that both:

@GremlinGroovy("it.outE('has').filter{it.inV().has('uuid', T.eq, uuid).hasNext()}")
FooEdge getFooEdgeFromUuid(@GremlinParam("uuid") String uuid);

and:

@GremlinGroovy("it.out('has').has('uuid', T.eq, uuid).inE('has')")

returns an Iterator so that's not so helpful either as you would need to return some form of List in your getFooEdgeFromUuid(). Perhaps the appropriate thing to do, assuming you know for a fact that this query will only and always return one edge would be to do:

@GremlinGroovy("it.out('has').has('uuid', T.eq, uuid).inE('has').next()")

I say "always" because without that, you'll get yourself a NoSuchElementException otherwise. In that way, to align types properly, you could do:

@GremlinGroovy("it.outE('has').filter{it.inV().has('uuid', T.eq, uuid)}")
Iterable<FooEdge> getFooEdgesFromUuid(@GremlinParam("uuid") String uuid);

Of course, all that may not work, because of this sentence I see in the docs:

It is possible to make use of a Gremlin path expression as a means of determining vertex adjacency via the GremlinGroovyModule.

In other words, use of @GremlinGroovy is for returning framed vertices (and not edges as you are trying to do). If the approach I suggested above doesn't work then your workaround using the @JavaHandler may be your best option.

stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • The reason why I was using hasNext() is because a filter closure expects a boolean result in order to determine whether or not a particular vertex passes through. – cscan Oct 01 '15 at 14:49