Spring and Neo4J integration - A Quick WebApp



Following my experimentation with MongoDB and the SpringData integration, I was keen to try out a few other NoSQL options - notably something outside of a document based data store. I had heard about a competition asking for submissions for Neo4J on the Heroku platform, which initially sparked my interest (although as of yet I have not tried it on Heroku) and seeing as Spring Data already had the Neo4J integration I thought I would have a go at it. Plus, I enjoy graphs as a data structure. I have fairly recently done some work on graphs having to implement Dijkstra's algorithm (also the A*) so this seemed like it was going to be fun.

Firstly, the documentation, in the form of an online e-book, for Neo4J Spring Data is awesome. Some guys have put together the e-book based on their experience setting up a Neo4J website and it really does cover everything from the first steps through to more complex stuff around traversal and transaction management. This also means, there is little point in me going through my every step in my app, as it wouldnt be very different from their advice, so most importantly, read this!!!

I will however, just highlight some interesting points i discovered along the way:

1. Simple Annotation based Entites
As you would expect, much like JPA or MongoDB, Neo4J supports simple annotation based configuration of your domain model to simply and quickly describe some pretty rich graph relationships. This is not that unexpected, as it is Spring after all, but worth noting that it is pretty comprehensive and easy to use.


2. Magic Repository Methods
A bit like in Grails, the Neo4J supports "magic" methods, that allow you to just define method names and the query implementation will be completed for you. For example, in your Movie repository (As per the book example, and also my example) if you defined a method such as:

Movie getMovieById(String id);

Then you do not need to provide an implementation, and Spring will automagically do the rest. (the convention being get[DOMAIN_ENTITY]By[ENTITY_PROPERTY]()

From the book: "In our wildest dreams we imagined the method names we would come up with, and what kinds of queries those could generate"

3. Arbor JS Graph Framework
A little while ago I discovered the Arbor JS framework for visualisation of graphs, and its really nice - I had to try and achieve something similar some time last year and got some of the way using core html5/JS but this library is a lot more comprehensive so wanted to have a go.
First, you should check out the demos over at http://arborjs.org/, they are really nice, and make for a really nice graph UI (see screenshot of my app).


4. The Data
I wanted to get some real data, and looked at a few big datasets available online such as the Stanford Large Data Set Network but being as Im only running locally, and I didnt really want to spend too much time getting the data into my graph model I decided to go for a far smaller, simpler dataset - this years Oscar nominations (actors/directors/movies/awards - hopefully you can make out the graph from the screenshot). The data I got from the Guardian (probably UK only) data set blog which also had some nice data sets in it, but this one seemed to be a small enough size for me not to loose too much time to the data.


As always, the code is up on my github, so feel free to check it out, fork/download/mistreat etc..

Retiring my Apps (website)

I have decided this weekend to retire my Android app development website (if you haven't already checked it out, you can still find it here for a while). The site was only really to provide more information and a contact method for anyone interested in the apps (and as part of an online portfolio really) but as my focus has been on other things (amongst them being Flutterby) I decided it was time to retire the site.

The apps will still be available of course, from the Android market, and I also updated my photo FX app "The Cutting Room" to be free now (as well as previously open sourcing the Android image processing libraries).


A Programmers Resolutions

The last week or two there was an article linked on HN about 12-month long resolutions for programmers - It was a nice read, so check it out

I would love to say Im gonna do them all, but there has got to be a very slim chance of that.. but there are a few i would like to complete, and some that I will complete just because it happens to match my other plans for the year:

(For more details, or examples of what the OP meant by each point jump through on the link)

  1. Go analog- So yeah, I'm gonna do this one. I love cooking anyway, and always looking to do more of that, and it just so happens I got an awesome BBQ over Christmas, so just waiting for some dry weather to get that out and start spit-roasting some meat. I would love to start a cookery blog, but given how long it takes between posts here, that might be tough.
  2. Stay healthy - would like to try, as always. But we will see.
  3. Embrace the uncomfortable.
  4. Learn a new programming language - Yes, Flutterby released I plan to sit down and learn. Probably a functional language.
  5. Automate.
  6. Learn more mathematics - would love to..
  7. Focus on security.
  8. Back up your data - Im sure I will do this, with so many cloud data offerings this is gonna happen (and already has in places).
  9. Learn more theory.
  10. Engage the arts and humanities- In another life there are loads of other things I would like to have been (wine taster, music producer, phtographer/film maker, movie critic) - and I try to embrace these other things when I get the chance, so maybe I will set up a movie blog for a month.. (watch this space!)
  11. Learn new software.
  12. Complete a personal project - Its on its way, Flutterby! this will hopefully be the January resolution hit at least.

 Check out the link. Has some interesting chat.

Formerly known as Butterfly


My side project, formerly known as "Butterfly", is approaching completion of its first beta approach, which is an exciting time. It has been in development in one way or another for some time, so its going to be great to see it finally getting an early release out there and (hopefully) seeing some feedback from real users.

It's in the final stages of getting together some slides to kind of show it off, sorting out a final URL and hopefully putting together a stand alone WAR file that will come bundled with Jetty/HSQL so users can just fire it up and test it out locally in an attempt to lower the barrier to adoption.

In the meantime, here is a bit of a blurb about what its actually all about..

Having worked in Enterprise software, on large scale projects spread across several geographic sites (often across several countries) we have seen and used several disparate, mediocre tooling to support collaboration and communication across the teams (even across teams on the same site), as an example of this, on my latest project engagement we have the following toolset:

  1. A web application to track defects/bugs
  2. A web application to manage work tickets (for example, requesting infrastructure team to patch/restart servers etc)
  3. A web application to manage internal work items/ToDo lists within the team
  4. An internal wiki
  5. Email (of course)
  6. Online chats

This was not unique to this project, but the obvious problem was that with all these disparate channels and mechanisms it made collaboration more difficult than it probably should be. For example, having multiple web apps to manage common tasks meant that most users were never "always on" any one tool, so to raise a ticket/defect/todo it involved opening app, logging in etc.  It also meant that knowledge was not easily centralised or searchable (searching for info across several web apps, email, and online chat archives is a pain in the ass) - The project attempts to tackle this inefficiency by building a single, user-centric web application that has these common communication and collaboration tasks at its heart whilst also borrowing metaphors and familiar mechanisms from popular social sites such as live feed "walls" for latest activity. Being user-centric it also means we can effectively capture the team/user relationships across the project.


Oh, and its called "Flutterby" now..


(there will be a more detailed write up shortly on the site once launched.. which is still pending the URL)

Google's AI Challenge

It is that time of year again that Google is sponsoring an AI challenge - It's a standard affair, you have to controll a set of ants and collect food and eventually defeat other ant hills, but its good fun and always a good opportunity to play around programming in a more competitive environment.

Full details are here, you can download the starter pack and get started in lots of programming languages, but unsuprisingly I have gone with Java for now - once you have the pack downloaded, they have some steps they recommend to get your ants doing the basics well, although you will obviously want to go beyond this minimum set, its a good chance to get your head around the object model and the APIs that are provided as standard.

I have just started this today and have completed the first 4 steps of the walkthrough, so not even started thinking about personal tactics and strategy.. so expect some posts to follow with those.

In the meantime, I am, as always, keeping my code on GitHub, so feel free to have a poke around how I have implemented the various steps in my code (only the first step of the tutorial is implemeneted in Java at the moment, the others are all currently in Python, so does require the slightest bit of imagination)

Integrating MongoDB & Spring

Further to my previous post with a deck walking through MongoDB & Spring integration, I also recently wrote it up as a technical article for work (my day job), and I thought I would share the detailed article here for you as well..


Introduction

With the explosion in the amounts of data being generated in recent years, more and more organisations are looking at alternative data storage options to the traditional relational model. This in turn has lead to huge growth in the NoSQL space, with leading web companies such as Facebook, Google, Twitter, Reddit, etc adopting NoSQL solutions.
Within the NoSQL space there are several different implementation options (Graph based DBs such as Neo4J, Wide Column DBS such as Cassandra and Haddop, Document based DBs such as MongoDB and CouchDB) and careful consideration is needed before choosing an implementation.
This article will look at integrating the Document oriented database MongoDB with a Spring MVC Web Application – it is important to note that due to the nature of Document based storage solutions, they are not applicable for all problems. For example, if the data you are modelling cannot naturally be stored as “documents”, then a Document-oriented DB probably isn’t the best solution (an easy way to think about whether the model can be stored as a document is to think of it being stored on paper – does it make sense for all the elements to be intrinsically grouped in to a single document? E.g. if you were storing an essay, all the chapters are intrinsically linked to the essay as a whole document, and a single chapter doesn’t make much sense as an individual object on its own).
For that reason, this article will look at a simple web app that allows users to create Resumes – Similar to an essay, resume storage is naturally suited to the Document based approach rather than a Relational approach.


Getting Started

This article will not cover details of creating a Spring MVC web application, and will assume a prior knowledge of the Spring MVC framework and core Spring principles. The example application itself is very simple, and there are several aspects of it that have not been included (these have been intentionally left out for simplicity), such as security/authentication features, advanced UI/screen flow/editing, etc, the purpose of the example application is purely to demonstrate MongoDB integration with Spring.
The source code for the application is all available from my GitHub Account (see links on the right), and if you want to follow the code below are the required pre-requisites:
  • Install MongoDB – this is a straight forward process and details can be found here: http://www.mongodb.org
  • Install Maven – the example project uses Maven to manage it dependencies, details can be found here: http://maven.apache.org/
  • Install STS Eclipse build and install the CloudFoundry extension (Optional) – If you want to follow the steps to deploy the application to the cloud then this is required
  • Sign up for a CloudFoundry account (www.cloudfoundry.com) (Optional) – Currently in Beta so its recommended that you sign up for the account as soon as possible as requests can take time to come through






Project Dependencies

Spring currently has a project underway to integrate core Spring functionality with various non–relational data technologies, including MongoDB, called “Spring Data”. We will use this library to facilitate our integration, so we will need to include the following maven dependency in our project pom:

              <dependency>
                     <groupId>org.springframework.data</groupId>
                     <artifactId>spring-data-mongodb</artifactId>
                     <version>1.0.0.M3</version>
              </dependency>


We also need to include the MongoDB Java driver:

              <dependency>
                     <groupId>org.mongodb</groupId>
                     <artifactId>mongo-java-driver</artifactId>
                     <version>2.6.5</version>
              </dependency>


And finally, to deploy on to CloudFoundry’s hosted service we need their runtime library:

              <dependency>
                     <groupId>org.cloudfoundry</groupId>
                     <artifactId>cloudfoundry-runtime</artifactId>
                     <version>0.7.1</version>
              </dependency>




Building the Domain Model

If you are familiar with using popular JPA frameworks in your Spring web apps (Hibernate/Eclipselink, etc) then this part should look familiar – Like any application we will need to create some objects to model our underlying data (the “M” in the MVC). For our simple application we will have three basic objects:



As you can see, we have three simple objects in our model, Resume, ResumePage, Section (we will just use these objects to split our document down in to several sections/chapters). One of the advantages of using Document-oriented DBs is that as it is schema-less, objects can be added to the document in the future without affecting existing data.
We model these objects as simple POJOs, just like modelling entities in JPA, but there are a few simple annotations Spring-Data provides for us
Resume.java:

@Document
public class Resume {
      
       @Id
       private String id;
      
       private List<ResumePage> pages = new ArrayList<ResumePage>();
...


That’s it! We use the @Document and @Id annotation to indicate any object that we want to treat as a Document, and the ID. We only need to add these annotations on our Resume object, as in this case the Resume is our document, we do not want to store our pages or sections as individual documents in themselves.



Data Access Layer

Now we have our data model we need to create our Data Access layer, so we can easily perform CRUD updates on our documents.
Creating our Data Access Objects is incredibly simple using MongoDB’s MongoRepository, and we automatically get basic CRUD functionality by just extending that interface. In our example app, we only want CRUD functionality so we just create a basic Interface that extends MongoRepository:

@Transactional
public interface IResumeRepository extends MongoRepository<Resume, String>{}

Next, in our Service layer we will auto-wire our new Interface in to our service classes (this is normal Spring stuff, using the @Autowired annotation we are telling Spring to handle the dependency injection for this interface):

@Repository("profileService")
@Transactional
public class ProfileService{

       @Autowired
       private IResumeRepository resumeRepo;


This makes the CRUD functionality available in our Service class to perform common functions, such as loadResume (in this case, we are using the resume owner’s name as the ID for the documents):

public Resume get(String userName) {
       return resumeRepo.findOne(userName.toLowerCase());
}


Or createResume:

       public Boolean createResume(Resume r) {
              try {
                     // Insert to db
                     resumeRepo.save(r);
                     return true;

              } catch (Exception e) {
                     //log exceptions here!
                     return false;
              }
       }


By simply extending the MongoRepository Interface and then auto-wiring it into our Service classes, we have provided basic CRUD functionality through the MongoRepository API as well as ensuring that our service class is not tightly coupled with the DAO implementation. However, often applications will need custom queries beyond basic CRUD. This can also be simply achieved using the MongoTemplate class provided, for example:

Query query = new Query(where("id").is(“rob”));
Resume r = mongoTemplate.findOne("mycollection", query, Resume.class);

The above query will retrieve the Resume belonging to “Rob”. The Query object provides rich API for accessing and updating documents in your data store.



Spring Configuration

The final step of our integration is to configure the Spring beans to handle the data source properties.
The Spring configuration resides in the Application Context XML file (in our case, it’s a file named “applicationContext.xml” and can be found in src/main/resources/META-INF/spring/.
This file is used to declare some of the Spring beans (although not all beans will be declared in here – some beans are declared using annotations, such as our Service classes), for our MongoDB integration we need to include the following configuration:

       <!-- Mongo Configuration -->
       <mongo:repositories base-package="com.tmm.nosql.mongodb.repo" />
      
       <bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
              <constructor-arg ref="mongoDbFactory" />
       </bean>
      
       <!-- local config -->
       <mongo:db-factory id="mongoDbFactory" dbname="resume_db" host="localhost" port="27017"/>


The first element of the config declares the name of the package that our Repositories are stored in (this is where the our DAO Repository lives) – we declare this so to enable the package to be scanned for relevant repository classes.
The second configuration element declares the Mongo Template bean (provided by the Spring Data library) and we declare that we want Spring to inject our MongoDbFactory bean using Constructor based Dependency Injection.
The final configuration option declares the MongoDbFactory that we will be injecting in to our MongoTemplate bean – here we need to define the database server and port name. The default port number is 27017, so unless you have altered from the standard MongoDB install and configuration then you should use these details.




Running the Application

Running Locally

To test the application, set up a Tomcat server within your Eclipse (IDE) and add the project to the server, start the server and navigate to http://localhost:8080/ and you should see a simple welcome page.

Running on CloudFoundry

Before running on CloudFoundry we need to make a very minor tweak to the configuration. Previously we had added the configuration option:

<mongo:db-factory id="mongoDbFactory" dbname="resume_db" host="localhost" port="27017"/>

As we are no longer running on localhost and want to bind these options to CloudFoundry’s services, we change this to:

<cloud:mongo-db-factory id="mongoDbFactory"/>

Simple enough again – we just declare our MongoDbFactory, and leave CloudFoundry to inject the required parameters.


The next step to deploying the application on CloudFoundry is to add a CloudFoundry server instance to your eclipse:
  • Open the “Servers” view in Eclipse (Window>Show View>Servers)
  • Right-click and select New>Server

  • Select VMWare > Cloud Foundry and then press the “Next” button
  • You will then have to enter your Cloud Foundry account information:



  • Complete your email and password information, leaving the URL as it is and select the Next button.
  • The final screen will give you the option to add the project to the server, add the server and press Finish



Now the Cloud Foundry server instance is setup within your IDE you need to configure the deployed application so you can bind it to the required services:
  • Double-click on your deployed project within the “Servers” view:


  • This will open the “Applications” page – you will notice in the bottom left had corner an empty box titled Services, 




  • Press the “Add Service” button to the top right of the Services panel:




  • The MongoDB service will now be listed in the Services box, now drag it across to the right to the “Application Services” section. The “Applications” panel should now appear something like this:



  • Press the “Start” button under the General tab, then watch the log as the application is started up on the CloudFoundry – there should be no errors reported
  • Now navigate to the URL you assigned to the application (this can be edited in the above panel under the “General” section


You now have a MongoDB powered NoSQL application running in the Cloud!