Hot questions for Using Neo4j in playframework

Top Java Programmings / Neo4j / playframework

Question:

I am using the below code to get information from nodes:

public void  allResturants (){
        final QueryResult<Map<String,Object>> result = engine.query("MATCH (n:`Restaurant`) RETURN n.name as name, n.website as web, n.address as address LIMIT 25", null);
         for (Map<String, Object> row : result) {
            String name=((String)row.get("name"));
            System.out.println("name is " + name);
         }
    }

Is there a way that I can select node direct by Query (like:MATCH(n:Restaurant) RETURN n) and then iterate and get its properties.

This query actually looks very long with more number of attribute:

MATCH (n:`Restaurant`) RETURN n.name as name, n.website as web, n.address as address LIMIT 25;

I want something like select * from tableName;.


Answer:

Return whole node:

MATCH (n:`Restaurant`) RETURN n LIMIT 25;

and then in java code:

public void  allResturants (){
    final QueryResult<Map<String,Object>> result = engine.query("...", null);
     for (Map<String, Object> row : result) {
        Node node = (Node) map.get("n"); // org.neo4j.graphdb.Node
        System.out.println("name is " + node.getProperty("name"));
     }
}

Works for both embedded and REST database.

Question:

Im using Neo4J OGM + Play Framework since 2 weeks succesfully, but today it doesn't work anymore. Every time I change something in my code, no matter if in a NodeEntity Class or in any other Class, it causes a java.lang.ClassNotFoundException when I try to get something from the database using the find method from org.neo4j.ogm.session.Session. Only if I clear the database and refill it I'm able to insert and get my NodesEntities.

Java version: 1.8 Scala version: 2.11.7 Sbt version: 2.6.3

build.sbt:

libraryDependencies += "org.neo4j" % "neo4j-ogm-core" % "3.0.0-RC1"
libraryDependencies += "org.neo4j" % "neo4j-ogm-bolt-driver" % "3.0.0-RC1"

Neo4JSessionFactory.java

public class Neo4jSessionFactory {

    private Config config;

    @Inject
    private Neo4jSessionFactory(Config config) {
        this.config = config;
    }


    public Session getNeo4jSession() {
        String uri = config.getString("ogm.db.uri");
        String username = config.getString("ogm.db.username");
        String password = config.getString("ogm.db.password");
        List<String> modelList = config.getStringList("ogm.db.models");

        String[] models = modelList.toArray(new String[modelList.size()]);

        Configuration configuration = new Configuration.Builder()
                .uri(uri)
                .credentials(username, password)
                .build();
        return new SessionFactory(configuration, models).openSession();
    }
}

application.conf

ogm{
   db{
     uri = "bolt://XXX.de:7687"
     username = "XXX"
     password = "XXX"
     models = ["neo4j.nodes", "neo4j.relationships", "neo4j.entities"]
   }
}

UserNode.java

@NodeEntity(label = "UserNode")
public class UserNode extends AbstractNode {

    @JsonProperty("username")
    private String username;

    @JsonProperty("firstname")
    private String firstname;

    @JsonProperty("lastname")
    private String lastname;

    @JsonProperty("email")
    private String email;

    @JsonProperty("password")
    private String password;

    @JsonProperty("picture")
    private String picture;

    @Relationship(type = Friendship.TYPE)
    @JsonProperty("friendships")
    private Set<Friendship> friendships = new HashSet<>();

    @Relationship(type = Posted.TYPE)
    @JsonProperty("postings")
    private Set<Posted> postings = new HashSet<>();

    @Relationship(type = Pinned.TYPE, direction = Relationship.INCOMING)
    @JsonProperty("pinnings")
    private Set<Pinned> pinnings = new HashSet<>();


    public UserNode() {
    }
}

UserService.java

public class UserService extends AbstractService<UserNode> {

    @Inject
    public UserService(Neo4jSessionFactory neo4jSessionFactory) {
        super(neo4jSessionFactory);
    }

    @Override
    public Class<UserNode> getEntityType() {
        return UserNode.class;
    }
}

AbstractService.java

public abstract class AbstractService<T extends AbstractNode> {

    private static final int DEPTH_LIST = 1;
    private static final int DEPTH_ENTITY = 1;

    protected Session session;

    @Inject
    public AbstractService(Neo4jSessionFactory neo4jSessionFactory) {
        this.session = neo4jSessionFactory.getNeo4jSession();
    }


    public Collection<T> findAll() {
        return session.loadAll(getEntityType(), DEPTH_LIST);    <-- (AbstractService:27)
    }

    public Optional<T> find(Long id) {
        return Optional.ofNullable(session.load(getEntityType(), id, DEPTH_ENTITY));
    }

    public void delete(Long id) {
        session.delete(session.load(getEntityType(), id));
    }

    public Optional<T> createOrUpdate(T entity){
        T updated = find(entity.getId())
                .map(existing -> {
                    entity.setCreated(existing.getCreated());
                    return entity;
                 }).orElse(entity);

        session.save(updated, DEPTH_ENTITY);
        return find(updated.getId());
    }
}

AbstactController.java

public Result all(){
    return toJsonResult(service.findAll());  <-- (AbstractCRUDController.java:19)
}

Exception

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[MappingException: Error mapping GraphModel to instance of neo4j.nodes.UserNode]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:255)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:180)
at play.core.server.AkkaHttpServer$$anonfun$13$$anonfun$apply$1.applyOrElse(AkkaHttpServer.scala:251)
at play.core.server.AkkaHttpServer$$anonfun$13$$anonfun$apply$1.applyOrElse(AkkaHttpServer.scala:250)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at play.api.libs.streams.Execution$trampoline$.execute(Execution.scala:70)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$DefaultPromise.scala$concurrent$impl$Promise$DefaultPromise$$dispatchOrAddCallback(Promise.scala:280)
Caused by: org.neo4j.ogm.exception.MappingException: Error mapping GraphModel to instance of neo4j.nodes.UserNode
at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:168)
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:124)
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:89)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:65)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:99)
at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:167)
at neo4j.services.AbstractService.findAll(AbstractService.java:27)
at controllers.AbstractCRUDController.all(AbstractCRUDController.java:19)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$2$$anonfun$apply$2.apply(Routes.scala:364)
at router.Routes$$anonfun$routes$1$$anonfun$applyOrElse$2$$anonfun$apply$2.apply(Routes.scala:364)
Caused by: org.neo4j.ogm.exception.MappingException: Unable to load class with FQN: neo4j.nodes.UserNode
at org.neo4j.ogm.metadata.reflect.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:109)
at org.neo4j.ogm.metadata.reflect.EntityFactory.newObject(EntityFactory.java:58)
at org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:179)
at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:165)
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:124)
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:89)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:65)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:99)
at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:167)
at neo4j.services.AbstractService.findAll(AbstractService.java:27)
Caused by: java.lang.ClassNotFoundException: neo4j.nodes.UserNode
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.neo4j.ogm.metadata.reflect.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:106)
at org.neo4j.ogm.metadata.reflect.EntityFactory.newObject(EntityFactory.java:58)
at org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:179)
at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:165)
at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:124)

Can anyone tell me if I'm going to go crazy or if it's still to be saved?


Answer:

I have tried your code and found that this error only occurs with a GET-request. I found this when I tried an insert with a POST-request. In this case, the "find"-method has found the appropriate class, but the subsequent GET-request does not. But I don't understand why it doesn't work with a GET-request. Maybe the header is different than a POST-request? It is also not a permanent solution to give up the get, to get the resource.

Question:

There is a Country class:

public class Country { 
    public int id;  
    public String name;
    public String locale;
}

I have to insert into neo4j.

What I am doing:

public void insert(Country country) {
        engine.query("create (n:Country {name:'"+country.name+"',id:"+country.id+",locale:'"+country.locale+"'})",null);
}

But I want to put Object directly to neo4j with label.

I am using play framework 2.3.7 with java 1.8 and libraryDependencies are

"org.neo4j" % "neo4j-rest-graphdb" % "2.0.1",
  "com.sun.jersey" % "jersey-server" % "1.7",
  "com.sun.jersey" % "jersey-core" % "1.7",
  "com.sun.jersey" % "jersey-json" % "1.7",

Answer:

You can use spring-data-neo4j for your requirement.Detailed steps are

1.Add dependencies to build.sbt

      "org.springframework.data" % "spring-data-neo4j" % "3.2.2.RELEASE",
      "org.springframework.data" % "spring-data-neo4j-rest" % "3.2.2.RELEASE",
      "org.springframework.data" % "spring-data-neo4j-tx" % "3.2.2.RELEASE"
  1. Global.java

    public class Global extends GlobalSettings {
        private ApplicationContext ctx;
    
        @Override
        public void onStart(Application app) {
            ctx = new AnnotationConfigApplicationContext(Neo4jConfig.class);
        }
    
        @Override
        public <A> A getControllerInstance(Class<A> clazz) {
            return ctx.getBean(clazz);
        }
    
        @Override
        public void onStop(Application app){
            ((AnnotationConfigApplicationContext)ctx).close();
        }
    

    }

  2. Configuration class for Neo4j connectivity

    @Configuration
    @EnableTransactionManagement
    public class Neo4jConfig extends Neo4jConfiguration {
    
          public Neo4jConfig() {
              setBasePackage("model");// My Entity package
          }     
       @Bean
       public SpringRestGraphDatabase graphDatabaseService() {      
            return new SpringRestGraphDatabase("http://localhost:7474/db/data");
      }   
      @Override
      @Bean(name = "transactionManager")
      public PlatformTransactionManager neo4jTransactionManager() throws Exception {
         return new JtaTransactionManagerFactoryBean(getGraphDatabaseService()).getObject();
      }    
    }
    
  3. Annotate your country class with NodeEntity

    @NodeEntity
    public class Country{ 
        public int id;  
        public String name;
        public String locale;
    }
    
  4. Use Neo4jTemplate for saving object to Graph DB

    @Autowired
    Neo4jTemplate template;
    
    public Country save(Country country){
        return template.save(country);
    }
    

Question:

I am trying to use Neo4J OGM 1.1.1 with Play 2 Java framework 2.4.2. but, I am see ClassNotFoundException when I run the application. Below is my session factory class:

package org.neo;

import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;

public class Neo4jSessionFactory {


    private static SessionFactory sessionFactory = new SessionFactory("org.neo.models");
    private static Neo4jSessionFactory factory = new Neo4jSessionFactory();

    public static Neo4jSessionFactory getInstance() {
        return factory;
    }

    private Neo4jSessionFactory() {

        System.setProperty("username", "neo4j");
        System.setProperty("password", "neo");
    }

    public Session getNeo4jSession() {
        return sessionFactory.openSession("http://localhost:7474");
    }
}
org.neo.models.School class
package org.neo.models;

import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import java.util.HashSet;
import java.util.Set;

@NodeEntity(label = "School")
public class School extends Entity {

    String name;

    @Relationship(type = "DEPARTMENT")
    Set<Department> departments;

    @Relationship(type = "STAFF")
    Set<Teacher> teachers;

    @Relationship(type = "HEAD_TEACHER")
    Teacher headTeacher;

    @Relationship(type = "STUDENT")
    Set<Student> students;

    public School() {
        this.departments = new HashSet<>();
        this.teachers = new HashSet<>();
        this.students = new HashSet<>();
    }

    public School(String name) {
        this();
        this.name = name;
    }

    @Override
    public String toString() {
        return "School{" +
                "id=" + getId() +
                ", name='" + name + '\'' +
                ", departments=" + departments.size() +
                ", teachers=" + teachers.size() +
                ", students=" + students.size() +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Department> getDepartments() {
        return departments;
    }

    public void setDepartments(Set<Department> departments) {
        this.departments = departments;
    }

    public Set<Teacher> getTeachers() {
        return teachers;
    }

    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }

    public Teacher getHeadTeacher() {
        return headTeacher;
    }

    public void setHeadTeacher(Teacher headTeacher) {
        this.headTeacher = headTeacher;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

Exception details can be found @ https://github.com/neo4j/neo4j-ogm/issues/34


Answer:

The issue is solved, it needed additional work in neo4j-ogm.

See: https://github.com/neo4j/neo4j-ogm/issues/34