Refactoring services

We need to change the default base trait for our dao packages to return Futures now. Let's start with BaseServices.scala:

package services

import scala.concurrent.Future

trait BaseService[A] {

def insert(a:A):Future[Unit]

def update(id:Long,a:A):Future[Unit]

def remove(id:Long):Future[Int]

def findById(id:Long):Future[Option[A]]

def findAll():Future[Option[Seq[A]]]

}

This last implementation reflects what's happening in the dao packages. Now we can move to the services implementation, and proceed with our refactoring.

Next we see ProductService.scala:

package services

trait IProductService extends BaseService[Product]{ def insert(product:Product):Future[Unit] def update(id:Long,product:Product):Future[Unit] def remove(id:Long):Future[Int] def findById(id:Long):Future[Option[Product]] def findAll():Future[Option[Seq[Product]]] def findAllProducts():Seq[(String,String)]

}

@Singleton class ProductService @Inject() (dao:IProductDao) extends IProductService{

import play.api.libs.concurrent.Execution.Implicits. defaultContext

def insert(product:Product):Future[Unit] = { dao.insert(product);

}

def update(id:Long,product:Product):Future[Unit] = { product.id = Option(id.toInt) dao.update(product)

}

def remove(id:Long):Future[Int] = { dao.remove(id)

}

def findById(id:Long):Future[Option[Product]] = { dao.findByld(id)

}

def findAll():Future[Option[Seq[Product]]] = { dao.findAll().map { x => Option(x) }

}

private def validateId(id:Long):Unit = { val future = findById(id) val entry = Awaits.get(5, future)

if (entry==null || entry.equals(None)) throw new RuntimeException("Could not find Product: " + id)

}

def findAllProducts():Seq[(String,String)] = { val future = this.findAll() val result = Awaits.get(5, future) val products:Seq[(String,String)] = result .getOrElse(Seq(Product(Some(0),"","",0)))

.toSeq

.map { product => (product.id.get.toString,product.name) } return products

}

}

There are a couple of changes here. First, we inject an IProductDao, and let Guice figure out the right injection that we need to be able to test with our old in-memory HashMap implementation, which will be covered later in this chapter. The changes involve new function signatures, using Awaits, and using Seq instead of List. Let's move to on ReviewService.scala now.

package services

trait IReviewService extends BaseService[Review]{ def insert(review:Review):Future[Unit] def update(id:Long,review:Review):Future[Unit] def remove(id:Long):Future[Int] def findById(id:Long):Future[Option[Review]] def findAll():Future[Option[Seq[Review]]]

}

@Singleton

class ReviewService @Inject() (dao:IReviewDao) extends IReviewService{

import play.api.libs.concurrent.Execution.

Implicits.defaultContext

def insert(review:Review):Future[Unit] = { dao.insert(review);}

def update(id:Long,review:Review):Future[Unit] = { review.id = Option(id.toInt) dao.update(review)

}

def remove(id:Long):Future[Int] = { dao.remove(id)

}

def findById(id:Long):Future[Option[Review]] = { dao.findById(id)

}

def findAll():Future[Option[Seq[Review]]] = { dao.findAll().map { x => Option(x) }

}

private def validateId(id:Long):Unit = { val future = findById(id) val entry = Awaits.get(5, future)

if (entry==null || entry.equals(None)) throw new RuntimeException("Could not find Review: " + id)

}

}

In the preceding code, we have the same kind of changes that we made for the product. Let's move to ImageService.scala, which is our last service.

package services

trait IImageService extends BaseService[Image]{ def insert(image:Image):Future[Unit] def update(id:Long,image:Image):Future[Unit] def remove(id:Long):Future[Int] def findById(id:Long):Future[Option[Image]] def findAll():Future[Option[Seq[Image]]]

}

@Singleton

class ImageService @Inject() (dao:IImageDao)

extends IImageService {

import play.api.libs.concurrent.Execution.

Implicits.defaultContext

def insert(image:Image):Future[Unit] = { dao.insert(image)

}

def update(id:Long,image:Image):Future[Unit] = { image.id = Option(id.toInt) dao.update(image)

}

def remove(id:Long):Future[Int] = { dao.remove(id)

}

def findById(id:Long):Future[Option[Image]] = { dao.findById(id)

}

def findAll():Future[Option[Seq[Image]]] = { dao.findAll().map { x => Option(x) }

}

private def validateId(id:Long):Unit = { val future = findById(id) val entry = Awaits.get(5, future)

if (entry==null ||entry.equals(None) ) throw new RuntimeException("Could not find Image: " + id)

}

}

We have refactored all services to use the new dao packages implementation. Now the next step is the move to the controllers.

 
Source