Quickstart

First, add the dependency to your project.

Maven

<dependency>
    <groupId>de.whitefrog</groupId>
    <artifactId>frogr-base</artifactId>
    <version>0.1.0</version>
</dependency>

Application

Next we will create the main entry point for the service.

public class MyApplication extends Application<Configuration> {
  public MyApplication() {
    // register the rest classes
    register("de.whitefrog.frogr.example.rest");
    // register repositories and models
    serviceInjector().service().register("de.whitefrog.frogr.example");
  }
  
  @Override
  public String getName() {
    return "frogr-base-example";
  }

  public static void main(String[] args) throws Exception {
    new MyApplication().run("server", "config/example.yml");
  }
}

As you can see there are two registry calls in the application’s constructor. register(...) let’s the application know in which package to look for rest classes. serviceInjector().service().register(...) tells the application where to look for models and repositories. More information about the Application entry point: Application

Configs

You may also have noticed there’s a config file used in the main method. This is required to setup our Dropwizard instance, so we have to create that one now. There’s a second config file needed, which configures our embedded Neo4j instance. By default these configs should be in your project in a directory ‘config’.

config/example.yml

server:
    applicationConnectors:
      - type: http
        port: 8282
    adminConnectors:
      - type: http
        port: 8286
    requestLog:
        appenders:
          - type: file
            currentLogFilename: logs/access.log
            threshold: ALL
            archive: false
logging:
    level: WARN
    loggers:
        de.whitefrog.frogr: INFO
        de.whitefrog.frogr.service.Search: DEBUG
        io.dropwizard.jersey.DropwizardResourceConfig: INFO
        io.dropwizard.jersey.jackson.JsonProcessingExceptionMapper: DEBUG
    appenders:
      # console logging
      - type: console
        logFormat: '[%d] [%-5level] %logger{36} - %msg%n'

Reference: Dropwizard Configuration

config/neo4j.properties

graph.location=target/graph.db

Reference: Neo4j Configuration

RelationshipTypes

We should add a class that holds our relationship types, so that we have consistent and convienient access. This is not a requirement but I highly recommend it. Doing so we don’t have to deal with string in Java code, which is never a good choice, right?

public abstract class RelationshipTypes {
  public static final String ChildOf = "ChildOf";
  public static final String MarriedWith = "MarriedWith";

  public enum t implements RelationshipType {
    ChildOf, MarriedWith
  }
}

Model

Now, let’s create a model. I recommend using Kotlin for that. All models have to extend the Entity class or implement the Model interface at least.

class Person() : Entity() {
  constructor(name: String) : this() {
    this.name = name
  }
  
  // Unique and required property
  @Unique
  @Indexed
  @Required
  var name: String? = null

  // Relationship to another single model
  @RelatedTo(type = RelationshipTypes.MarriedWith, direction = Direction.BOTH)
  var marriedWith: MarriedWith? = null
  // Relationship to a collection of models
  @Lazy @RelatedTo(type = RelationshipTypes.ChildOf, direction = Direction.OUTGOING)
  var parents: List<Person> = ArrayList()
  @Lazy @RelatedTo(type = RelationshipTypes.ChildOf, direction = Direction.INCOMING)
  var children: List<Person> = ArrayList()
  
  companion object {
    @JvmField val Name = "name"
    @JvmField val MarriedWith = "marriedWith"
    @JvmField val Children = "children"
  }
}

As you can see, we used the relationship types created before, to declare our relationships to other models.

Repository

Normally we would create a repository for persons. But we won’t need extra methods for this tutorial and frogr will create a default repository if it can’t find one. If you need more information visit Repositories.

Service

Next we’ll have to create the REST service layer. There’s a base class, that provides basic CRUD operations, so you only have to add methods for special cases. Of course you can also use any other JAX-RS annotated class.

@Path("person")
public class Persons extends CRUDService<PersonRepository, Person> {
  @GET
  @Path("init")
  public void init() {
    // insert some data
    try(Transaction tx = service().beginTx()) {
      if(repository().search().count() == 0) {
        repository().init();
        tx.success();
      }
    }
  }
}