sc_ray
sc_ray

Reputation: 8043

Traits not implemented in finagle service

I have a simple finagle service as follows:

import com.twitter.finagle.{Http,Service}
import com.twitter.util.{Await, Future}
import java.net.InetSocketAddress
import org.jboss.netty.handler.codec.http._
import org.jboss.netty.buffer.ChannelBuffers.copiedBuffer
import org.jboss.netty.util.CharsetUtil
import net.liftweb.json._
import com.twitter.finagle.http.{Request,Response,RichHttp}
import com.twitter.finagle.builder.ServerBuilder

case class Add(num1:Int, num2:Int)
case class Result(result:Int)  

trait Transformer[R1,T,U,R2] {
  def extractPayload(r:R1):T
  def responsePayload(u:U):R2
}

object Transformer{
  implicit object AddPayloadTransformer 
        extends Transformer[HttpRequest,Add,Result,HttpResponse]{
   implicit val formats = DefaultFormats

   def extractPayload(r:HttpRequest):Add = {
        val body = r.getContent
    val length = body.readableBytes()
    val bytes = new Array[Byte](length)
    body.getBytes(body.readerIndex(),bytes,0,length)
    val bodyStr = new String(bytes)
    parse(bodyStr).extract[Add]
    }

   def responsePayload(u:Result):HttpResponse = {   
    val result = u.result
    val response = Response(HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK)
        response.setContentTypeJson()       
        response.setContentString(
          s"""
            {
            "result": $result
            }
           """)
        response.httpResponse
   }   
  }
}

object AdditionServer extends App with Transformer[HttpRequest,Add,Result,HttpResponse]{
 private def add(add:Add):Result = Result(add.num1 + add.num2) 

 private def additionHandler(req:HttpRequest): HttpResponse = {
     val addPayload = extractPayload(req)
     val result = add(addPayload)
     responsePayload(result)    
 }   

 val service = new Service[HttpRequest,HttpResponse] {
     def apply(req: HttpRequest): Future[HttpResponse] = 
    {
       Future.value(additionHandler(req))
    }
 }

  val server = Http.serve(":8080", service)
  Await.ready(server)
  println("Started service")                
}

When I try to compile it, I get the following exception:

AdditionService.scala:49: object creation impossible, since:
[error] it has 2 unimplemented members.
[error] /** As seen from object AdditionServer, the missing signatures are as follows.
[error]  *  For convenience, these are usable as stub implementations.
[error]  */
[error]   def extractPayload(r: org.jboss.netty.handler.codec.http.HttpRequest): Add = ???
[error]   def responsePayload(u: Result): org.jboss.netty.handler.codec.http.HttpResponse = ???
[error] object AdditionServer extends App with Transformer[HttpRequest,Add,Result,HttpResponse]{
[error]        ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

To my knowledge I am implementing the traits with their proper signature.

Can somebody point out what might be going wrong here.

Thanks

Upvotes: 1

Views: 157

Answers (1)

AdditionServer is the object which is extending Transformer. In your code, this object is not defining neither extractPayload nor responsePayload thus the compilation error you get.

You should move your methods definitions from the trait companion object to AdditionServer

object AdditionServer extends App with
Transformer[HttpRequest,Add,Result,HttpResponse] {

import Transformer._

def extractPayload(r:HttpRequest):Add = {
        val body = r.getContent
    val length = body.readableBytes()
    val bytes = new Array[Byte](length)
    body.getBytes(body.readerIndex(),bytes,0,length)
    val bodyStr = new String(bytes)
    parse(bodyStr).extract[Add]
}

def responsePayload(u:Result):HttpResponse = {   
    val result = u.result
    val response = Response(HttpVersion.HTTP_1_1,
            HttpResponseStatus.OK)
        response.setContentTypeJson()       
        response.setContentString(
          s"""
            {
            "result": $result
            }
           """)
        response.httpResponse
   }   
}

If you'd rather keep your methods defined at the companion object you can refer to them from AdditionServer:

object Transformer{
  implicit object AddPayloadTransformer 
  extends Transformer[HttpRequest,Add,Result,HttpResponse]{
   implicit val formats = DefaultFormats

   def extractPayload(r:HttpRequest):Add = {
        val body = r.getContent
        val length = body.readableBytes()
        val bytes = new Array[Byte](length)
        body.getBytes(body.readerIndex(),bytes,0,length)
        val bodyStr = new String(bytes)
        parse(bodyStr).extract[Add]
    }

   def responsePayload(u:Result):HttpResponse = {   
        val result = u.result
        val response = Response(HttpVersion.HTTP_1_1,
            HttpResponseStatus.OK)
        response.setContentTypeJson()       
        response.setContentString(
          s"""
            {
            "result": $result
            }
           """)
        response.httpResponse
   }   
  }
}

object AdditionServer extends App with
Transformer[HttpRequest,Add,Result,HttpResponse]{

   def extractPayload(r:HttpRequest):Add = Transformer.extractPayload(r)

   def responsePayload(u:Result):HttpResponse = Transformer.responsePayload(u)

  ...
  ...

Upvotes: 2

Related Questions