Graphs in the Cloud: Spring + Neo4j on Heroku

Last week I hosted a webinar about running Java apps on Heroku that use the Spring Framework and the Neo4j graph database. Here is the recording of that webinar:

In the webinar I began by deploying a copy of the Spring MVC + Hibernate template app from on Heroku. Then I made a few modifications to the app to switch the persistence from Hibernate / JPA to Neo4j. You can get the full source code on GitHub.

Here is a quick recap of what I did to switch the template app to use Neo4j:

  1. Added the Neo4j Heroku Add-on:
    heroku addons:add neo4j
  2. Added the Spring Data Neo4j dependencies (optionally you can remove the unused JPA dependencies) to the “pom.xml” Maven build descriptor:
  3. Modified the “src/main/java/com/example/service/” interface to use the Neo4j GraphRepository:
    package com.example.service;
    import com.example.model.Person;
    public interface PersonService extends GraphRepository<Person> {
  4. Removed the unneeded “src/main/java/com/example/service/” DAO.
  5. Modified the “src/main/java/com/example/model/” POJO to be a @NodeEntity (instead of JPA Entity) and switched the “id” primary key property to be a Long annotated as a @GraphId:
    package com.example.model;
    public class Person {
        private Long id;
        // the rest is omitted
  6. Modified the “src/main/java/com/example/controller/” Spring MVC controller to use the new “PersonService”, take a Long parameter in the “deletePerson” method, and make the “deletePerson” and “addPerson” methods transactional:
    package com.example.controller;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import com.example.model.Person;
    import com.example.service.PersonService;
    import java.util.Map;
    public class PersonController {
        private PersonService personService;
        public String listPeople(Map<String, Object> map) {
            map.put("person", new Person());
            map.put("peopleList", personService.findAll().iterator());
            return "people";
        @RequestMapping(value = "/add", method = RequestMethod.POST)
        public String addPerson(@ModelAttribute("person") Person person) {
            return "redirect:/people/";
        public String deletePerson(@PathVariable("personId") Long personId) {
            return "redirect:/people/";
  7. Then I modified the “src/main/resources/applicationContext.xml” Spring config file to use a file for local Neo4j storage in the “default” profile and then in the “prod” profile the “NEO4J_REST_URL”, “NEO4J_LOGIN”, and “NEO4J_PASSWORD” environment variables are used to connect to the Neo4j Heroku add-on service:
    <?xml  version="1.0" encoding="UTF-8"?>
    <beans xmlns=""
        <context:annotation-config />
        <context:spring-configured />
        <context:component-scan base-package="com.example" />
        <neo4j:repositories base-package="com.example.service"/>
        <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
        <tx:annotation-driven />
        <beans profile="default">
            <neo4j:config storeDirectory="target/neo4j-db"/>
        <beans profile="prod">
            <bean class="" id="graphDatabaseService">
                <constructor-arg index="0" value="#{systemEnvironment['NEO4J_REST_URL']}"/>
                <constructor-arg index="1" value="#{systemEnvironment['NEO4J_LOGIN']}"/>
                <constructor-arg index="2" value="#{systemEnvironment['NEO4J_PASSWORD']}"/>
            <neo4j:config graphDatabaseService="graphDatabaseService"/>
  8. After testing my changes locally (which actually didn’t work in my webinar due to a problem with Eclipse) I committed my changes to the git repo and pushed them to Heroku:
    git push heroku master

If you want to just skip to a working example on the cloud, simply follow the instructions in the project README.

Hopefully that helps you get started with Neo4j and Java applications on the cloud!

BTW: If you watched the webinar, you probably noticed that my Maven and Eclipse were misbehaving. Turns out that M2E didn’t read my Maven config and all I had to do was right-click on the project, select Maven, and then Update Project Configuration. That got everything back in sync. My excuse for not being able to figure that out during the demo… I usually use IntelliJ IDEA. :)

  • Saraandreson8

    I apply all the instruction of what  you did to switch the template app to use N .Its great and i  got all my expectations.Thanks for sharing.

  • Jon

    Hello James, Thx for the tutorial…

    I’ve been following all these steps, but I’m always getting the exception:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘personController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.service.PersonService com.example.controller.PersonController.personService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘personService’: Cannot resolve reference to bean ‘neo4jTemplate’ while setting bean property ‘neo4jTemplate’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘’: Cannot resolve reference to bean ‘graphDatabaseService’ while setting bean property ‘graphDatabaseService’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘graphDatabaseService’ defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class []: Constructor threw exception; nested exception is java.lang.NullPointerException

    I’ve also tried the GitHub tutorial at However I have the same issue.

    Any ideia what is going on?

    • jon

      Actually I’ve realized I have only ‘NEO4J_URL’ Environment Variables in my list after I perform ‘heroku config’. Is there some kind of trick to obtain NEO4J_REST_URL, NEO4J_LOGIN and NEO4J_PASSWORD or these should be available automatically ? Thank you.

    • James Ward

      Something is getting a null and it shouldn’t be. Perhaps this is something coming from the configuration?