Julian
Julian

Reputation: 51

Scala + Lift + REST - Returning Arrays with serveJx

I have a class that extends RestHelper to serve items in both xml and json. Currently, I am implementing the "serve"-method to return the entities in xml:

object Rest  extends RestHelper {

serve {

    case "supplier" :: "findAll" :: _ XmlGet _
        => supplierListToXml(Supplier.findAll)

}

def supplierListToXml(suppliers : List[Supplier]) = {
    <suppliers>{suppliers.mapConserve(f=> f.toXml)}</suppliers>
}

}

I want to serve the same items as json aswell, depending on the Accept-header, using the serveJx-method (explained in http://www.assembla.com/wiki/show/liftweb/REST_Web_Services).

The class Supplier implements Convertable, and I implemented a conversion-method within the Rest-class:

object RestApi extends RestHelper {
implicit def cvt: JxCvtPF[Convertable] = {
   case (JsonSelect, c, _) => c.toJson
   case (XmlSelect, c, _) => c.toXml
 }

serveJx {
    case Get("2.0" :: "supplier" :: "head" :: _,_)
        => Full(Supplier.findAll.head)
}

}

... and this works find, when I serve a single supplier. But when I want to return a list of suppliers (List[Supplier]), the conversion-method cannot be applied.

    case Get("2.0" :: "supplier" :: "findAll" :: _,_)
        => Full(Supplier.findAll.toList)

... and I get the compilation-error:

"could not find implicit value for parameter cvt:com.mycompany.api.RestApi.JxCvtPF[ScalaObject]"

Can someone please give me an example of how to modify the cvt-method to be able to convert list of convertables to a LiftResponse?

Cheers! /J

Upvotes: 0

Views: 552

Answers (1)

Julian
Julian

Reputation: 51

I found a solution to the cvt-method. Change the type to implicit def cvt: JxCvtPF[Any] to be able to match specific classes. Then implement the list of convertables as such:

//Generic list templates
    case (JsonSelect, c : List[Convertable], _) => JArray(for{item <- c} yield item.toJson)
    case (XmlSelect, c : List[Convertable], _) => <list>{c.mapConserve(f => f.toXml)}</list>

Full solution:

object Rest  extends RestHelper {
implicit def cvt: JxCvtPF[Any] = {

    //Generic list templates
    case (JsonSelect, c : List[Convertable], _) => JArray(for{item <- c} yield item.toJson)
    case (XmlSelect, c : List[Convertable], _) => <list>{c.mapConserve(f => f.toXml)}</list>

    //Single-items of convertable
    case (JsonSelect, c : Convertable, _) => c.toJson
    case (XmlSelect, c : Convertable, _) => c.toXml
}
serveJx {

    case "supplier" :: "findAll" :: _ Get _
        => Full(Supplier.findAll)

    case "channelPackage" :: "findAll" :: _ Get _
        => Full(ChannelPackage.findAll)

    case "channelPackage" :: "findFromSupplierId" :: supplierId :: _ Get _
        => Full(Supplier.find(supplierId).head.channelPackages)

    case "device" :: "findAll" :: _ Get _
        => Full(Device.findAll)

    case "device" :: "findFromSupplierId" :: supplierId :: _ Get _
        => Full(Supplier.find(supplierId).head.devices)
}

}

Upvotes: 1

Related Questions