4/29/2012

The simple Apache Solr client for Scala

I pushed solr-scala-client into github. This is a simple Apache Solr client for Scala wrapping SolrJ.

The basic concept of solr-scala-client is providing fluent interface and wrapping SolrJ classes by Scala collection API. This is an example to register documents into the Solr server which is working at localhost:8983.

import jp.sf.amateras.solr.scala._

val client = new SolrClient("http://localhost:8983/solr")

client
  .add(Map("id"->"1", "name" -> "ThinkPad X201s"))
  .add(Map("id"->"2", "name" -> "ThinkPad X220"))
  .add(Map("id"->"3", "name" -> "ThinkPad X121e"))
  .commit

add() takes a variable-length argument. So an example above could be rewritten as follows:

client.add(
  Map("id"->"1", "name" -> "ThinkPad X201s"),
  Map("id"->"2", "name" -> "ThinkPad X220"),
  Map("id"->"3", "name" -> "ThinkPad X121e")
).commit

Next, see the following example to search document using the query.

// query
val result: List[Map[String, Any]] =
  client.query("name:%name%")
    .fields("id", "manu", "name")
    .sortBy("id", Order.asc)
    .getResult(Map("name" -> "ThinkPad"))

result.foreach { doc =>
  println("id: " + doc("id"))
  println("name: " + doc("name"))
  println("--")
}

%VARNAME% in the query is replaced by given parameters as Map and the result is returned as List[Map[String, Any]].

The current version of solr-scala-client does not support facet search yet. I wish to support it in the near future. And I'm also planning about using case class to specify document or parameters instead of Map.

4/15/2012

mirage 1.1.5 and mirage-scala 0.0.4 is now available!

Today, we released Mirage 1.1.5 and mirage-scala 0.0.4!

Mirage is a simple SQL centric database access library and mirage-scala is the wrapper of Mirage for Scala. See the following URL to know about Mirage:

This release contains some important new features for mirage-scala. Mirage update is only small bug fix. So I introduce new features of mirage-scala 0.0.4 in this entry.

Improvement of SqlManager interface

Some methods of SqlManager had a java.lang.Class parameter which specifies the entity class in the previous version. But in mirage-scala 0.0.4, it modified to the generics type parameter.

// Until mirage-scala 0.0.3
val books = sqlManager.getResultList(
  classOf[Book], 
  Sql("SELECT * FROM BOOK"))

// In mirage-scala 0.0.4
val books = sqlManager.getResultList[Book](
  Sql("SELECT * FROM BOOK"))

Improvement of case class entity

mirage-scala can handle case class as the entity. But it required the default constructor as below:

@Table(name="BOOK")
case class Book(
  @(PrimaryKey @field)(generationType = IDENTITY)
  bookId: java.lang.Long,
  bookName: String,
  author: String,
  price: Option[Int]) {

  // This is not required in mirage-scala 0.0.4
  def this() = this(null, null, null, None)

}

The default constructor of case class is not required no longer in mirage-scala 0.0.4.

Wrapping primary key by Pk[T]

In mirage-scala 0.0.4, Pk[T], Id[T] and Auto are added. You can use Pk[T] to wrap the property which corresponds to the primary key. It is useful when the primary key is set by the database. For example, it's auto incremented column.

@Table(name="BOOK")
case class Book(
  @(PrimaryKey @field)(generationType = IDENTITY)
  bookId: Pk[Long],
  bookName: String,
  author: String,
  price: Option[Int])

val book = Book(
  Auto, 
  "Mirage in Action",
  "Naki Takezoe",
  25)

sqlManager.insertEntity(book)

If you have to set the value of the primary key, you can use Id[T] instead of Auto.

@Table(name="BOOK")
case class Book(
  @(PrimaryKey @field)(generationType = APPLICATION)
  bookId: Pk[Long],
  bookName: String,
  author: String,
  price: Option[Int])

val book = Book(
  Id(1), 
  "Mirage in Action",
  "Naki Takezoe",
  25)

sqlManager.insertEntity(book)

Anyway, mirage-scala became more scalanized database access library in 0.0.4. I hope mirage-scala will help your development with Scala!

4/08/2012

Simple wrapper of PicoContainer for Scala

I tried SubCut to resolve dependency of components in Scala. However I think The Cake Pattern might be better than SubCut because it's so complex more than necessary and not transparent.It's similar to the service locator, not the DI container. I need a DI container which is more simple and intuitive. It's sufficient that supports constructor injection.

There are PicoContainer in Java World. So I wrote a simple wrapper of PicoContainer for Scala:

It does not cover all features of PicoContainer. But it might be enough for my current use :-)

2/12/2012

Getting Started with mirage-scala

mirage-scala is the simple and powerful library to access RDBMS from Scala. I introduce how to use mirage-scala with sbt.

At first, add the following dependency into your build.sbt:

And create the jdbc.properties and put it on the root of classpath.

Next, you have to create the entity class. mirage-scala supports both of mutable and immutable style as entity class. This is the example of immutable style entity class:

Ready for mirage-scala. Let's try to use it!

You can insert, update and delete a record using SqlManager and entity classes. And also you can select a record by the primary key.

When you must select records by the more complex query, you can do it using 2way-SQL which is the powerful feature of mirage-scala. I would like to write about it in the next entiry.

mirage-scala 0.0.3 is now available!

mirage-scala is the wrapper of Mirage for Scala. It provides the best solution to access RDBMS from Scala.

New features in mirage-scala 0.0.3:

  • Case class (immutable model) is available as entity.
  • Option[T] is available as property type.

By these new features, mirage-scala became the more suitable library for Scala to access RDBMS.

mirage-scala is still under preview release. So any request or feedback welcome!

Mirage 1.1.4 is now available!

Mirage is a simple SQL centric database access library. See the following URL to know about Mirage:

New features in Mirage 1.1.4:

  • Added RailsLikeNameConverter as an optional NameConverter.
  • Added FieldPropertyExtractor as an optional implementation of PropertyExtractor.
  • BugFix: Avoid depending on JDBC 4.0 (Java6) API in DefaultValueType
  • Chopping semicolon from the end of the SQL file.
  • Improve: Avoid using type Exception/RuntimeException to make interfaces intension revealing
  • Added SqlManagerImpl#setValueTypes to make it easier to configure valueTypes using Spring framework
  • BugFix: PropertyExtractor extracts static or final field
  • Improvement: DefaultResultEntityCreator just reqires no-argument constructor. It really doesn't matter if the constructor is public.
  • Improvement: Make ValueType parameterized. If you implement custom ValueTypes, these is not compatible in this version.
  • Added BreakIterationException to discontinue iteration search.
  • BugFix: @Column is available for the select query.

Since this version, we provide a source code cross reference generated by Sorcerer. It generates so rich HTML based cross reference which provide references search like Eclipse. See the follwing URL:

I hope Mirage helps your development. Enjoy!

11/03/2011

Simple HTTP Client for Scala

I'm writing a Simple HTTP Client for Scala. This is a simple example of GET request:

using (new SimpleHttpClient()){ client =>
  val content: Option[String] = client.get(
    url = "http://localhost:8080/"
  )
  content match {
    case Some(s) => println(s)
    case None => println("Request Failed.")
  }
}

You can give request parameters to get() method. And it's possible to send POST request to use post() method instead of get() method. The second example shows how to give request parameters with the POST request:

using (new SimpleHttpClient()){ client =>
  val content: Option[String] = client.post(
    url = "http://localhost:8080/",
    params = Map("q" -> "Scala"),
    encode = "UTF-8"
  )
  ...
}

In default SimpleHttpClient returns the response body as Option[String]. You can handle the response to give the your own response handler. The response handler has to be a function has a signature (HttpResponse => T).

using (new SimpleHttpClient()){ client =>
  val content: Array[Byte] = client.post(
    url = "http://localhost:8080/",
    handler = { r: HttpResponse =>
      r.getStatusLine.getStatusCode match {
        case HttpStatus.SC_OK => 
          EntityUtils.toByteArray(r.getEntity())
        case _ => 
          throw new RuntimeException("Request Failed.")
      }
    }
  )
  ...
}

SimpleHttpClient also supports http proxy. You can give proxy settings to the constructor.

using(new SimpleHttpClient(
    "proxy.example.com:8080")){ client =>
  ...
}

I'm making useful utilities like this HTTP Client for development of general Scala based applications at scala-utils.