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 heroku.com/java 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:
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rest</artifactId>
        <version>2.0.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.2.0.Final</version>
    </dependency>
  3. Modified the “src/main/java/com/example/service/PersonService.java” interface to use the Neo4j GraphRepository:
    package com.example.service;
     
    import com.example.model.Person;
    import org.springframework.data.neo4j.repository.GraphRepository;
     
    public interface PersonService extends GraphRepository<Person> {
     
     
    }
  4. Removed the unneeded “src/main/java/com/example/service/PersonServiceImpl.java” DAO.
  5. Modified the “src/main/java/com/example/model/Person.java” 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;
     
    import org.springframework.data.neo4j.annotation.GraphId;
    import org.springframework.data.neo4j.annotation.NodeEntity;
     
    @NodeEntity
    public class Person {
     
        @GraphId
        private Long id;
     
        // the rest is omitted
  6. Modified the “src/main/java/com/example/controller/PersonController.java” 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;
     
    @Controller
    public class PersonController {
     
        @Autowired
        private PersonService personService;
     
        @RequestMapping("/")
        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)
        @Transactional
        public String addPerson(@ModelAttribute("person") Person person) {
            personService.save(person);
            return "redirect:/people/";
        }
     
        @RequestMapping("/delete/{personId}")
        @Transactional
        public String deletePerson(@PathVariable("personId") Long personId) {
            personService.delete(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="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                               http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                               http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd">
     
        <context:annotation-config />
        <context:spring-configured />
        <context:component-scan base-package="com.example" />
     
        <neo4j:repositories base-package="com.example.service"/>
     
        <mvc:annotation-driven/>
     
        <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" />
        </bean>
     
        <tx:annotation-driven />
     
        <beans profile="default">
            <neo4j:config storeDirectory="target/neo4j-db"/>
        </beans>
     
        <beans profile="prod">
            <bean class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase" 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']}"/>
            </bean>
     
            <neo4j:config graphDatabaseService="graphDatabaseService"/>
        </beans>
     
    </beans>
  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. :)

Posted in Heroku, Neo4j, Spring | Leave a comment

Play 2 Java Tutorial

I’ve created a Play 2 Tutorial and posted it on GitHub! The tutorial covers how to:

Each section has a corresponding branch in git so you can diff against my version to see if you’ve done everything correctly. Right now this is just for Play 2 with Java and Ebean but I’m working on doing this for Play 2 with Scala as well.

You can see a live demo of the final app at:
play2torial.herokuapp.com

It’s a pretty simple app but it should get you started building Play 2 apps and deploying them on the cloud with Heroku. If you want to take the shortcut to the end and get your own copy of the app running on Heroku then just do the following:

  1. Install git and the Heroku Toolbelt.
  2. Signup for an account on Heroku. (Don’t worry, this stuff is free.)
  3. Clone the play2torial git repo:
    git clone git://github.com/jamesward/play2torial.git
  4. Login to Heroku:
    heroku login
  5. Create a new app on Heroku (from within the play2torial directory):
    heroku create --stack cedar
  6. Upload the app to Heroku (from within the play2torial directory):
    git push heroku java-heroku_update:master
  7. Check out your app on the cloud:
    heroku open
  8. If you want to run the app locally, install Play 2 and then run:
    git checkout java-heroku_update
    play ~run

I hope this helps you learn Play 2! Let me know if you have any questions or comments. Thanks!

Posted in Java, Play Framework | 8 Comments

Heroku, Java, Play and Neo4j Presos: Denver JUG, Atlanta JUG, London Flash UG & Webinar

Over the next couple weeks I’ll be doing two Java User Group presentations, a Flash Platform User Group presentation and one Webinar. Hope to see you at one of these events:

Posted in Heroku, Java, Neo4j, Play Framework | 2 Comments

Heroku Presos: Denver Open Source UG and Future Insights Live

This week I’ll be doing two presentation about Heroku:

Hope to see you there!

Posted in Heroku, HTML5, Java | Leave a comment

WebJars in Spring MVC

Last week I announced the WebJars project that allows you to specify your web libraries (JavaScript, CSS, etc) as dependencies in your Java web applications. With some help from Jeremy Grelle I was able to get a simple WebJars Spring MVC example working.

First you will need to add the WebJars repository to your build. For Maven, just add the following to your “pom.xml” build file:

    <repositories>
        <repository>
            <id>webjars</id>
            <url>http://webjars.github.com/m2</url>
        </repository>
    </repositories>

Then add a WebJar dependency, like Twitter Bootstrap:

        <dependency>
            <groupId>com.github.twitter</groupId>
            <artifactId>bootstrap</artifactId>
            <version>2.0.2</version>
        </dependency>

Then you need to add a resource handler to Spring MVC that maps requests from a given path to files in the classpath. The WebJars are all inside of a “public” directory. If you are using Java configuration in Spring then you would do the following:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
 
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/public/**").addResourceLocations("classpath:/public/");
  }
}

Or if you are using XML config then add the following to your Spring config:

<mvc:resources mapping="/public/**" location="classpath:/public/"/>

Then you can reference a WebJar’s assets with something like:

<link rel='stylesheet' media='screen' href='/public/stylesheets/bootstrap.min.css'>

How easy is that? Now you are managing your web libraries as versioned dependencies and you even get transitive dependencies! Check out the full source code for this example on GitHub: https://github.com/jamesward/spring_webjars_demo

Right now there are only a couple of WebJars so if you need something else then simply request a new one via a new issue on GitHub.

Please let me know what you think about this. Thanks!

Posted in Java, Spring, WebJars | 8 Comments

Introducing WebJars – Web Libraries as Managed Dependencies

Update: I’ve created a Spring MVC WebJars example.

Our web apps are using more and more web libraries like jQuery, Backbone.js and Twitter Bootstrap. The traditional way to use those libraries is to locate & download the JavaScript and CSS source then just copy it into a project. To me this resembles how we used to just copy JAR files into a project’s WEB-INF/lib dir. But why not do with web libraries like we now do with Java libraries and specify them as managed dependencies? This allows us to declaratively set the version, use a consistent version across an application, and easily deal with transitive dependencies. Then we just need web frameworks that can serve static assets from JAR files and we are good to go! Luckily Play 2 and Dropwizard both have out-of-the-box support for this. So I decided to give it a try…

I packaged up some JavaScript and CSS web libraries into JARs, put them into a Maven repo and it worked! And thus the WebJars project was born!

Lets look at an example for how to use the Twitter Bootstrap WebJar in a Play 2 app. First we need to add the WebJars Maven repo to the Play 2 dependency resolvers and specify Bootstrap as a dependency. For Play 2 this is done in the “project/Build.scala” file. Here is one for my Play 2 WebJars Demo project:

import sbt._
import Keys._
import PlayProject._
 
object ApplicationBuild extends Build {
 
    val appName         = "play2_webjars_demo"
    val appVersion      = "1.0-SNAPSHOT"
 
    val appDependencies = Seq(
      "com.github.twitter" % "bootstrap" % "2.0.2"
    )
 
    val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      resolvers += "webjars" at "http://webjars.github.com/m2"
    )
 
}

Now to use Bootstrap in a Scala template, we can just do:

<link rel='stylesheet' media='screen' href='@routes.Assets.at("stylesheets/bootstrap.min.css")'>

The “@routes.Assets.at” thing just gets a reverse route for the URL that will serve the “bootstrap.min.css” file from the Bootstrap WebJar. Note: It’s not necessary in Play 2 to use the reverse routing but it is a type safe way to get a URL. Based on the default routes in Play 2 the route to that file will be “/assets/javascripts/bootstrap.min.js” which we could have used instead.

Now here is the super cool part… The Bootstrap WebJar depends on jQuery so now I can also just use jQuery:

<script type='text/javascript' src='@routes.Assets.at("javascripts/jquery.min.js")'></script>

That is super simple and now I’m managing my web libraries as dependencies!

Note: Play 2 actually puts a copy of jQuery in the default project template but hopefully for Play 2.1 they will pull it out and instead use the jQuery WebJar. In my demo project I’ve removed that copy of jQuery because it’s no longer needed.

If you want to use WebJars with Dropwizard then first setup the Maven “pom.xml” file with the WebJars repo and add the dependency:

    <repositories>
        <repository>
            <id>webjars</id>
            <url>http://webjars.github.com/m2</url>
        </repository>
    </repositories>
 
    <dependencies>
        <dependency>
            <groupId>com.github.twitter</groupId>
            <artifactId>bootstrap</artifactId>
            <version>2.0.2</version>
        </dependency>
    </dependencies>

Then add an “AssetBundle” that will serve static assets in the “public” directory on the “/public” URL path:

    addBundle(new AssetsBundle("/public/", 0, "/public"));

Now you can load the static assets in a web page:

    <link rel='stylesheet' media='screen' href='/public/stylesheets/bootstrap.min.css'>
    <script type='text/javascript' src='/public/javascripts/jquery.min.js'></script>

Get the full source code for the Dropwizard WebJars demo on GitHub.

I’m sure there are other Java web frameworks that support WebJars, so if you know of one, let me know and I’ll try to create more demo projects.

Right now there are just a couple WebJars in the repository but if you’d like to see others then create a new issue on GitHub and I’ll build a new WebJar.

Let me know what you think about WebJars. Thanks!

Posted in Dropwizard, Java, Play Framework, WebJars | 22 Comments

Heroku for Java, Scala & Play at the Houston JUG and NFJS Virginia

This week I will be presenting about Running Java, Scala, and Play apps on Heroku at the Houston JUG and at No Fluff Just Stuff in Reston, VA:

Hope to see you there!

Posted in Heroku, Java, Play Framework, Scala | Leave a comment

Play Framework 2 & HTML5 on Heroku at Philly ETE and Devoxx Paris

Over the next few weeks I’ll be doing a few presentations about Java, Scala, Play Framework 2, HTML5, and Heroku:

Hope to see you there!

Posted in Heroku, HTML5, Java, Play Framework | 8 Comments

Java on Heroku at NH JUG and DevNexus 2012

This week I’ll will be doing a few presentations about running Java and Play apps on Heroku:

Hope to see you there!

Posted in Heroku, Java, Play Framework | Leave a comment