Setup

To use Molecule we need to define our database schema in a Schema definition file and then tell sbt about it. When compiling our project from the command line, all necessary boilerplate code is then automatically generated by the sbt MoleculePlugin.

1. SBT build settings

Add the following to your build files:

project/build.properties:

sbt.version=0.13.16

project/buildinfo.sbt:

addSbtPlugin("org.scalamolecule" % "sbt-molecule" % "0.4.5")

build.sbt:

lazy val yourProject = project.in(file("demo"))
  .enablePlugins(MoleculePlugin)
  .settings(
    resolvers ++= Seq(
      "datomic" at "http://files.datomic.com/maven",
      "clojars" at "http://clojars.org/repo",
      Resolver.sonatypeRepo("releases")
    ),
    libraryDependencies ++= Seq(
      "org.scalamolecule" %% "molecule" % "0.13.2",
      "com.datomic" % "datomic-free" % "0.9.5697"
    ),
    moleculeSchemas := Seq("demo") // paths to your schema definition files...
  )

Molecule 0.13.2 for Scala 2.12.6 is available at Sonatype.

2. Paths to Schema definition files

We use the moleculeSchemas sbt settings key to tell the sbt MoleculePlugin where we have our Schema definition files.

A Schema definition file contains a plain Scala object where you define partitions/namespaces/attributes of your Datomic database. The MoleculePlugin uses the information defined there to create all the boilerplate code needed to use Molecule in your code.

You can have a single or several Schema definition files in a project. Each definition file defines a single database. This is useful if you for instance want to experiment with various database designs during development.

Schema definiton files should reside in directories named schema anywhere in your source code.

Use the moleculeSchemas sbt settings key to list the directories in your project source code that contains your schema directories.

Say you have a project demo and a single Schema definition file YourDomainDefinition.scala defining your database:

Then you simply add moleculeSchemas := Seq("demo") as we saw above.

Multiple schemas

In the main Molecule project’s examples module we have several Schema definition files:

And we then list the paths to those like this in our build.sbt:

moleculeSchemas := Seq(
  "molecule/examples/dayOfDatomic",
  "molecule/examples/graph",
  "molecule/examples/mbrainz",
  "molecule/examples/seattle"
)

3. Compile

Now that you have created a schema definition file and told sbt about where to find it, you can compile your project from the terminal

> cd yourProjectRoot
> sbt compile

The MoleculePlugin will now automatically as part of the compilation process do 5 things:

  1. Generate Molecule boilerplate dsl source code files (in the src_managed directory in target)
  2. Generate a schema file with the necessary code to transact the Datomic schema
  3. Compile the generated code
  4. Package both the source code and compiled classes into two jars and place them in the lib directory of your module
  5. Remove the generated source code and compiled classes

The MoleculePlugin create the jars so that you can use the boilerplate code without having to recompile any generated boilerplate code each time you recompile your project. In our demo example two jars are created:

4. Use Molecule

The MoleculePlugin has now created all the necessary boilerplate code so that we can start using Molecule. We can create a fresh in-memory Datomic database by supplying the generated Schema transaction code in YourDomainSchema (from the example above):

import molecule._
implicit val conn = recreateDbFrom(demo.schema.YourDomainSchema)

With the implicit Datomic connection available we can start making molecules:

import demo.dsl.yourDomain._

// Insert data
Person.name("John").age(26).gender("male").save

// Retrieve data
val (person, age, gender) = Person.name.age.gender.get.head

Next