Question

I am new with liftweb and scala. I am developing json-rest api for rss agregator and I have two problems:

package my.domain

import net.liftweb.http._
import net.liftweb.http.rest._
import net.liftweb.json.JsonAST._
import net.liftweb.common.{Box,Full,Empty,Failure,ParamFailure}


import my.domain.model.{RssItem}

object ContentRest extends RestHelper {
 def getFirstRssItem = {
  val item = RssItem.find(ByField(RssItem.title, "test"))
  item.title
 }
 serve {
     case "api" :: "static" :: _ XmlGet _=> <b>Static</b>
     case "api" :: "static" :: _ JsonGet _ => JString("string")
 }
}

I get errors on both first and second lines of getFirstRssItem method:

First is that compiler can't find ByField method - what i need to import?

Second is that compiler says it can't find method title in item val. According to liftweb wiki I may call field's name as method but item has the type Box[my.domain.model.RssItem]. What am I doing wrong? RssItem model:

package my.domain.model

import net.liftweb.mapper._

class RssItem extends KeyedMapper[Long, RssItem] {

    def getSingleton = RssItem

    def primaryKeyField = id
    object id extends MappedLongIndex(this)
    object title extends MappedString(this, 255)
    object description extends MappedText(this)
    object pubDate extends MappedDateTime(this)
}

object RssItem extends RssItem with KeyedMetaMapper[Long, RssItem] {
    def dbTable = "items"
}
Was it helpful?

Solution

As Debilski points out, find() return a Box[RssItem] which is Empty if there are no items or Full(item) if an item was found, so getting the title requires a map() or using the for comprehension (which is syntactic sugar on map/flatMap/filter).

In terms of your query, you want By() rather than ByField(). I've cleaned up your code so it compiles:

object ContentRest extends RestHelper {
  def getFirstRssItemTitle = {
    for {
      item <- RssItem.find(By(RssItem.title, "test"))
    } yield item.title
  }

  serve {
    case "api" :: "static" :: _ XmlGet _=> 
    for {
      title <- getFirstRssItemTitle ?~ "No RSS data"
    } yield <b>{title}</b>
  }
}

Note that if there are no items in the database, then you'll return a 404 with "No RSS data" in the body (rather than a null pointer exception.)

I hope this helps.

OTHER TIPS

Wondering whether you can try using net.liftweb.mapper.By (instead of ByField), something like ...

import net.liftweb.mapper.By

val item = RssItem.find(By(RssItem.title, "test")

Find returns a Box, (which you can use just like Option,) because it is not clear whether an actual element can be found.

Instead of item.title, you would write something like

item.map(_.title) openOr "untitled"

item.map(_.title) gives you a Box of the title which either contains the title or is empty (in case no item was found). Without a Box, you’d have a Null error there. openOr then either returns the contents of the Box or specified default value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top