//Karthik Srinivasan

Product Engineer, CTO & a Beer Enthusiast
Experiments, thoughts and scripts documented for posterity.

Quirky Personal Projects

LinkedIn

Email me

Spray.io REST service - MongoDB - Lesson 4

View the lessons list at https://github.com/karthik20522/SprayLearning

Now that we have Spray Service Setup and Routes defined, we can now hookup the database to add and fetch customer information. For the database I am using MongoDB and Casbah. Casbah is a Scala toolkit for MongoDB. Casbah is a "toolkit" rather than "driver", as Casbah is a layer on top of the official mongo-java-driver for better integration with Scala.

To get Casbah setup, we need to add casbah and it's related dependencies to the Build.scala file.
Note that we have slf4j and scala logging in the dependencies. Without slf4j you would get "Failed to load class org.slf4j.impl.StaticLoggerBinder" error.

In my example, I have created a MongoFactory that has 3 functions: getConnection, getCollection and closeConnection.
    import com.mongodb.casbah.MongoCollection
    import com.mongodb.casbah.MongoConnection

    object MongoFactory {
    private val SERVER = "localhost"
    private val PORT = 27017
    private val DATABASE = "customerDb"
    private val COLLECTION = "customer"

    def getConnection: MongoConnection = return MongoConnection(SERVER)
    def getCollection(conn: MongoConnection): MongoCollection =
    return conn(DATABASE)(COLLECTION)
    def closeConnection(conn: MongoConnection) { conn.close }
    }


Now that we have our Factory method, the next is building the data access class for inserting and fetching data. Following code snippet has 2 operations:
class CustomerDal {

  val conn = MongoFactory.getConnection

  def saveCustomer(customer: Customer) = {
    val customerObj = buildMongoDbObject(customer)
    val result = MongoFactory.getCollection(conn).save(customerObj)
    val id = customerObj.getAs[org.bson.types.ObjectId]("_id").get
    println(id)
    id
  }

  def findCustomer(id: String) = {
    var q = MongoDBObject("_id" -> new org.bson.types.ObjectId(id))
    val collection = MongoFactory.getCollection(conn)
    val result = collection findOne q

    val customerResult = result.get

    val customer = Customer(
      firstName = customerResult.as[String]("firstName"),
      lastName = customerResult.as[String]("lastName"),
      _id = Some(customerResult.as[org.bson.types.ObjectId]("_id").toString()),
      phoneNumber = Some(customerResult.as[String]("phoneNumber")),
      address = Some(customerResult.as[String]("address")),
      city = Some(customerResult.as[String]("city")),
      country = Some(customerResult.as[String]("country")),
      zipcode = Some(customerResult.as[String]("zipcode"))
    )

    customer //return the customer object
  }

  //Convert our Customer object into a BSON format that MongoDb can store.
  private def buildMongoDbObject(customer: Customer): MongoDBObject = {
    val builder = MongoDBObject.newBuilder
    builder += "firstName" -> customer.firstName
    builder += "lastName" -> customer.lastName
    builder += "phoneNumber" -> customer.phoneNumber.getOrElse("")
    builder += "address" -> customer.address.getOrElse("")
    builder += "city" -> customer.city.get
    builder += "country" -> customer.country.get
    builder += "zipcode" -> customer.zipcode.getOrElse("")
    builder.result
  }
}
Now to integrate this to the service:
trait CustomerService extends HttpService with Json4sSupport {
  val customerRoutes =
    path("addCustomer") {
      post {
        entity(as[JObject]) { customerObj =>
          complete {
            val customer = customerObj.extract[Customer]
            val customerDal = new CustomerDal
            val id = customerDal.saveCustomer(customer)
            id.toString()
          }
        }
      }
    } ~
      path("getCustomer" / Segment) { customerId =>
        get {
          complete {
            //get customer from db using customerId as Key
            val customerDal = new CustomerDal
            val customer = customerDal.findCustomer(customerId)
            customer
          }
        }
      }
}
More information and resources on Casbah: