Skip to content

Using Neo4j with Vaadin Part 1: Creating the Architecture

peholmst edited this page Mar 22, 2011 · 6 revisions

This is the first part in a series of articles about developing Vaadin-applications that use Neo4j for storing data. In this article, we are going to look at the architecture for a simple Neo4j-enabled Vaadin application and also create a very simple application that uses a Neo4j database.

The architecture that we are going to implement will look like this:

System architecture

At the bottom, we have the Neo4j database. In this article, we are going to use the embedded Neo4j-database. However, as we will always access it through an interface, you could easily change it to the highly available database later on, if needed.

In the middle, there is a simple business logic layer and at the top a Vaadin-based UI layer. Everything runs inside a Tomcat 7 web server (we use some of the new Servlet 3.0 annotations in this example).

You can find the source code of the working demo application here. You may use the source in any way you like, just remember that Neo4j is licensed under AGPL 3.0 (commercial usage requires a commercial license).

Bootstrapping Neo4j

Now, the first thing we want to do is instantiate Neo4j so that we can start using it. However, we only want to run it as a singleton that is shared by all the Vaadin application instances. There are a number of ways of achieving this; in this article we are going to use a servlet context listener. We are going to start the database when the servlet context starts up, and shut it down when the context is destroyed (in this example, the code for actually retrieving the Neo4j database directory has been omitted, but you could e.g. read it from a system property or a properties file):

@WebListener
public class Neo4jBootstrapper implements ServletContextListener {

    private GraphDatabaseService graphDb;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        String myNeo4jDirectory = ....
        // Code for retrieving the database directory omitted.
        graphDb = new EmbeddedGraphDatabase(myNeo4jDirectory);
        Backend.init(graphDb);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        if (graphDb != null) {
            graphDb.shutdown();
        }
    }
}

Please note the usage of the new @WebListener annotation - no web.xml deployment descriptor is needed.

Once the database service instance has been created, we have to make it available to the application. To do this, we use a backend singleton class:

public class Backend {

    private static Backend INSTANCE;
    
    static void init(GraphDatabaseService graphDb) {
        INSTANCE = new Backend(graphDb);
    }
    
    public static Backend getInstance() {      
        return INSTANCE;
    }
    
    private final GraphDatabaseService graphDb;
    
    private Backend(GraphDatabaseService graphDb) {
        this.graphDb = graphDb;
    }
    
    public GraphDatabaseService getGraphDb() {
        return graphDb;
    }
}

Now, once the servlet context has been started, applications can access the graph database by invoking Backend.getInstance().getGraphDb(). When the context is destroyed (e.g. due to the application being redeployed or the server itself shutting down), the graph database will also be shut down gracefully.

Adding the Business Logic Layer

Now, we are ready to add the business layer. Depending on the requirements of your application, this can be either easy or hard. In this article, we are going to create a very simple messaging board application:

  • Users can post messages to the board.
  • Each message may be tagged with hash tags (e.g. #foo #bar)
  • Users can search for tags.
  • When the user selects a tag, all messages that have the specified tag are shown.

In order to implement this, we use the following Neo4j graph model:

Graph model


If you have used Neo4j before, you should have no problems reading the graph model. However, for those of you who are new to Neo4j, here is a quick walk-through:

  • At the top of the graph is a reference node. This is a built-in node that is always present and is used to reference other nodes.
  • The reference node is connected to two subreference nodes via the MESSAGES and TAGS relationships.
  • The subreference node for messages is connected to all messages in the system via the CONTAINS MESSAGE relationship.
  • The subreference node for tags is connected to all tags in the system via the CONTAINS TAG relationship.
  • A message node is connected to all its tag nodes via the IS TAGGED BY relationship.

As the system will require some text searching, we also need to maintain a few indexes; otherwise we would have to traverse large parts of the graph while looking for matching nodes (please see the source code for more information on how this is done).


In this case, we can get away with only using strings for moving data between the business logic layer and the UI, so our service interface becomes:

public interface Service {

    void storeMessage(String message);

    Collection<String> getTaggedMessages(String tag);

    Collection<String> getTagsStartingWith(String tagprefix);
}

As no Neo4j objects escape from the business logic layer, we do not have to worry about any serialization or transaction handling issues. Now, I know that in real world applications, you almost never get away with a design as simple as this (or if you do, chances are your application is in serious need of refactoring). The purpose of this example is just to test that we can in fact access the Neo4j database from our application.

As our service is stateless, there is no use in creating new instances of it for every Vaadin application instance and so we use the singleton pattern again:

public class ServiceImpl implements Service {

    private static Service INSTANCE = new ServiceImpl();

    private ServiceImpl() {
    }

    public static Service getInstance() {
        return INSTANCE;
    }

    protected GraphDatabaseService getGraphDb() {
        return Backend.getInstance().getGraphDb();
    }

    @Override
    public void storeMessage(String message) {
        // Implementation omitted
    }

    @Override
    public Collection<String> getTaggedMessages(String tag) {
        // Implementation omitted
    }

    @Override
    public Collection<String> getTagsStartingWith(String tagprefix) {
        // Implementation omitted
    }

Please check the source code for the complete implementation of the service.

Plugging in the UI

We are now ready to add the UI to our application:

Screenshot of the demo application

As the purpose of this article is to demonstrate how to use Neo4j with Vaadin and not how to create Vaadin GUIs, I am not going to show the actual UI code here. Instead, we are just going to look at the parts that are interested from an architectural point of view.

First, we need a servlet for "running" the GUI:

@WebServlet(urlPatterns = "/*")
public class DemoAppServlet extends AbstractApplicationServlet {

    @Override
    protected Application getNewApplication(HttpServletRequest request) throws ServletException {
        return new DemoApp();
    }

    @Override
    protected Class<? extends Application> getApplicationClass() throws ClassNotFoundException {
        return DemoApp.class;
    }
}

Please note the usage of the new @WebServlet annotation - we still do not need a web.xml deployment descriptor.

Second, we need a Vaadin application class that implements the UI:

public class DemoApp extends Application {

    @Override
    public void init() {
        Window mainWindow = new Window("Neo4j Vaadin Demo 1");
        initMainWindow(mainWindow);
        setMainWindow(mainWindow);
    }

    public Service getService() {
        return ServiceImpl.getInstance();
    }

    private void initMainWindow(Window mainWindow) {
        // Implementation omitted
    }
}

As you can see, we can access the business logic layer using the service implementation singleton.


Please note, that it is very important that the calls to the service always go through the singleton and not via a locally stored reference to the singleton such as this:

private transient Service theService = ServiceImpl.getInstance();

public void myIncorrectMethod() {
    // DON'T DO THIS!
    theService.storeMessage("hello world");
}

public void myCorrectMethod() {
    // THIS IS BETTER!
    ServiceImpl.getInstance().storeMessage("hello world");
}

The first method will sometimes work and sometimes not as the service implementation is not serializable. If the session has been restored from disk (e.g. due to a server restart), the service instance in the example above will be null, leading to null pointer exceptions when the user tries to use the application.

The second method will always work, but strongly couples the code to the ServiceImpl class. A better way would be to introduce a protected getter method that wraps the call to the getInstance() method. During unit testing, this method could then be overridden to return a mock of the service.


We have now created a simple Vaadin application that uses Neo4j for storing data. In the next article, we are going to add a domain model to our application.

You can’t perform that action at this time.