To connect to the already running MongoDB server, create a Mongo client class with a hostname and port number:
- class MongoClient(val host:String, val port:Int)
The primary constructor is a constructor that needs to be called directly or indirectly from overloaded constructors when creating the instance MongoClient. You’ll look into overloaded constructors shortly. In Scala, the primary constructor for a class is coded inline with the class definition. In this case, the constructor takes two parameters: host and port. The host parameter specifies the address of the server, and port specifies the port in which the MongoDB server is waiting for the connection.
Because all the constructor parameters are preceded by val, Scala will create immutable instance values for each of them. The following example creates an instance of a Mongo client and accesses its properties:
Like Java or C#, Scala also uses the new keyword for creating instances of a class. But wait a minute—where’s the body of the MongoClient class? In Scala that’s optional. You can create classes without any class body. Creating a class like a JavaBean with only a getter and setter would be easy in Scala, as in the following:
When parameters are prefixed with var, Scala creates mutable instance variables. The val and var prefixes are optional, and when both of them are missing, they’re treated as private instance values, not accessible to anyone outside the class:
Note that when Scala creates instance values or variables, it also creates accessors for them. At no point in time are you accessing the field directly. The following MongoClient definition is equivalent to the class MongoClient(val host:String, val port:Int) definition.
- class MongoClient(private val _host:String, private val _port:Int) {
- def host = _host
- def port = _port
- }
Most of the time you’ll have MongoDB running on the localhost with default port 27017. Wouldn’t it be nice to have an additional zero-argument constructor that defaults the host and port number so you don’t have to specify them every time? How about this:
- class MongoClient(val host:String, val port:Int) {
- def this() = this("127.0.0.1", 27017)
- }
- class MongoClient(val host:String, val port:Int) {
- def this() = {
- val defaultHost = "127.0.0.1"
- val defaultPort = 27017
- this(defaultHost, defaultPort)
- }
- }
This poses an interesting challenge when you have to do some operation before you can invoke the other constructor. Later in this chapter, you’ll look into a companion object and see how it addresses this limitation. To make a connection to the MongoDB you’ll use the com.mongodb.Mongo class provided by the Mongo Java driver:
- package ch3
- import com.mongodb.Mongo
- class MongoClient(val host:String, val port:Int) {
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- }
- class MyScript(host:String) {
- require(host != null, "Have to provide host name")
- if(host == "127.0.0.1") println("host = localhost")
- else println("host = " + host)
- }
How is Scala doing this? Scala puts any inline code defined inside the class into the primary constructor of the class. If you want to validate constructor parameters, you could do that inside the class (usually at the top of the class). Let’s validate the host in the MongoClient:
- package ch3
- import com.mongodb.Mongo
- class MongoClient(val host:String, val port:Int) {
- require(host != null, "You have to provide a host name")
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- }
- package ch3
- import com.mongodb.Mongo
- class MongoClientV2(val host:String, val port:Int)
- extends Mongo(host, port){
- require(host != null, "You have to provide a host name")
- def this() = this("127.0.0.1", 27017)
- }
NOTE.
Even though extending com.mongodb.Mongo as a superclass is a completely valid way to implement this driver, you’ll continue to use the earlier implementation because that will give you more control over what you want to expose from the Scala driver wrapper, which will be a trimmed-down version of the complete Mongo Java API. Before going any further, I’ll talk about Scala imports and packages. This will help you to work with the Mongo library and structure your code.