Chapter 10. Curtains Up! - Get it running

10.1. Requisites - Populating the database

Time to put this on display. But we needed some test data first. So we wrote a small class for populating the database which could be called from our controller. To make it safe to call several times we added index lookups to check for existing entries. A simple /populate endpoint for the controller that called it would be enough for now.

@Service
public class DatabasePopulator {

  @Autowired GraphDatabaseContext ctx;
  @Autowired MoviesRepository repository;

  @Transactional
  public List<Movie> populateDatabase() {
      Actor tomHanks = new Actor("1", "Tom Hanks").persist();
      Movie forestGump = new Movie("1", "Forrest Gump").persist();
      forestGump.setYear(1994);
      tomHanks.playedIn(forestGump,"Forrest");
      return asList(forestGump);
  }}

@Controller
public class MovieController {

  private DatabasePopulator populator;

  @Autowired
  public MovieController(DatabasePopulator populator) {
      this.populator = populator;
  }

  @RequestMapping(value = "/populate", method = RequestMethod.GET)
  public String populateDatabase(Model model) {
      Collection<Movie> movies=populator.populateDatabase();
      model.addAttribute("movies",movies);
      return "/movies/list";
  }
}

        

<%@ page session="false" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:choose>
  <c:when test="${not empty movie}">
    <h2>${movie.title}</h2>
    <c:if test="${not empty movie.roles}">
    <ul>
    <c:forEach items="${movie.roles}" var="role">
      <li>
        <a href="/actors/${role.actor.id}"><c:out value="${role.actor.name}" /> as <c:out value="${role.name}" /></a><br/>
      </li>
    </c:forEach>
    </ul>
    </c:if>
  </c:when>
  <c:otherwise>
      No Movie with id ${id} found!
  </c:otherwise>
</c:choose>
            

See the misused GET parameter for that (don't do this at home, the REST guys will be upset). This is only for running it from the browser address line. Better use POST and curl for the call. So we called the URI and it showed the single added movie on screen.

10.2. Behind the scenes - Peeking at the Datastore

10.2.1. Eye candy - Neoclipse visualization

After filling the database we wanted to see what the graph looked like. So we checked out two tools that are available for inspecting the graph. First Neoclipse, an eclipse RCP application or plugin that connects to existing graph stores and visualizes their content. After getting an exception about concurrent access, I learned that I have to use Neoclipse in readonly mode when my webapp had an active connection to the store. Good to know.

10.2.2. Hardcore "Hacking" - Neo4j Shell

Besides our movies and actors connected by ACTS_IN relationships there were some other nodes. The reference node which is an automatically provided "root node" in Neo4j and can be used to anchor subgraphs for easier access. And Spring Data Graph also represented the type hierarchy of my entities in the graph. Obviously for some internal housekeeping and type checking.

For console junkies there is also a shell that can reach into a running neo4j store (if that one was started with enableRemoteShell) or provide readonly access to a graph store directory.

neo4j-shell -readonly -path data/graph.db
            

It uses some shell metaphors like cd and ls to navigate the graph. There are also more advanced commands like using indexes and traversals. I tried to play around with them in this shell sesson.

neo4j-sh[readonly] (0)$ ls
(me) --[SUBREF_java.lang.Object]-> (3)
(me) --[SUBREF_org.neo4j.cineasts.domain.Movie]-> (6)
(me) --[SUBREF_org.neo4j.cineasts.domain.Person]-> (8)
(me) --[SUBREF_org.neo4j.cineasts.domain.User]-> (2)
neo4j-sh[readonly] (0)$ cd 6
neo4j-sh[readonly] (6)$ ls
*class =[org.neo4j.cineasts.domain.Movie]
*count =[39]
(me) <-[INSTANCE_OF]-- (The Matrix Revolutions,123)
(me) <-[INSTANCE_OF]-- (The Matrix Reloaded,110)
(me) <-[INSTANCE_OF]-- (The Matrix,93)
...
neo4j-sh[readonly] (6)$ cd 93
neo4j-sh[readonly] (The Matrix,93)$ ls
*description  =[Neo is a young software engineer and part-time hacker who is singled out by some mysterious...]
*genre        =[Action]
*homepage     =[http://whatisthematrix.warnerbros.com/]
*id           =[603]
*imageUrl     =[http://cf1.imgobject.com/posters/606/4bc909d0017a3c57fe003606/the-matrix-mid.jpg]
*imdbId       =[tt0133093]
*language     =[en]
*lastModified =[1299968642000]
*releaseDate  =[922831200000]
*runtime      =[136]
*studio       =[Warner Bros. Pictures]
*tagline      =[Welcome to the Real World.]
*title        =[The Matrix]
*trailer      =[http://www.youtube.com/watch?v=UM5yepZ21pI]
*version      =[324]
(me) <-[ACTS_IN]-- (Marc Aden,109)
...
(me) <-[ACTS_IN]-- (Keanu Reeves,96)
(me) <-[DIRECTED]-- (Andy Wachowski,95)
(me) <-[DIRECTED]-- (Lana Wachowski,94)
(me) --[INSTANCE_OF]-> (6)
(me) <-[RATED]-- (Micha,1)