Monday, February 27, 2012

Scala Source Code and Density

I love Scala. It enables me to write concise / dense and clear code at the same time.

Take for example the piece of code below.
Had I written it in Java, it would be much longer, while at the same time less dense, and with much less clarity of what it is doing.

val site = config.sites.find(_.name == siteName).getOrElse(
    throw new IllegalArgumentException("Cannot find site " + siteName))
val group = config.groups.find(_.name == groupName).getOrElse(
    throw new IllegalArgumentException("Cannot find group " + groupName))
group.repositories.foreach { repo =>
  val repoDir = new File(group.path, repo.name)
  println("Backing up to repository %s at %s starting..." format (repo.name, repoDir))
  if (repoDir.mkdir())
    println("Created directory %s" format repoDir)
  repo.facets.foreach { facet =>
    println("Exporting facet %s..." format facet.name)
    val source = site.databases.find(_.name == facet.source).getOrElse(
        throw new IllegalArgumentException(
          "Facet %s references non-existing database %s" format (facet.name, facet.source)))
    println("Source database is %s:%s at %s" format (source.kind, source.name, source.url))
    (source.kind, facet) match {
      case ("neo4j", Facet(name, sourceName, "node", typeName, "json")) =>
        val outFileName = new File(name + ".json")
        println("Exporting %s nodes to %s" format (typeName, outFileName))
        val dbDir = new File(new URI(source.url))
        println("Neo4j database directory: %s" format dbDir)
        val graphDb = new EmbeddedReadOnlyGraphDatabase(dbDir.getPath)
        val (rowMeta, rows) = try {
          val exporter = new Neo4jNodeExporter(graphDb, typeName)
          println("Fetching meta...")
          val rowMeta = exporter.fetchMeta()
          println("Columns are: " + rowMeta.columns.mkString(", "))
          val rows = exporter.export(rowMeta)
          (rowMeta, rows)
        } finally {
          graphDb.shutdown()
        }
        
        println("Reading rows...")
        val mapper = new ObjectMapper
        mapper.getSerializationConfig.set(Feature.INDENT_OUTPUT, true)
        val jsonRows = rows.map { row =>
          val obj = mapper.createObjectNode()
          for ((value, i) <- row.values.view.zipWithIndex) {
            if (value != null)
              obj.put(rowMeta.columns(i), value)
          }
          obj
        }
        val jsonArray = mapper.createArrayNode().addAll(jsonRows.toList)
        val jsonData = mapper.createObjectNode()
        jsonData.put("data", jsonArray)
        val outFile = new File(repoDir, outFileName.toString)
        
        print("Writing %s..." format outFile)
        mapper.writeValue(outFile, jsonData)
        println(" [OK]")
        
      case x: Any => println("Skipping unrecognized facet: " + x)
    }
  }
  println("Backing up to repository %s finished." format repo.name)
}

Scala is also fantastic at storing ad-hoc object graph / trees, check a look a this :

  sites = List(
    Site(name = "dev", databases = List(
      Database(name = "graph", kind = "neo4j", url = "file:///together/project/SatukanCinta/satukancinta-neo4j-db_dev_1.6/"))),
    Site(name = "test",
      databases = List(Database(name = "graph", kind = "neo4j", url = "file:///together/project/SatukanCinta/dumptest/graph")))),
  groups = List(Group(name = "main", path = "/together/project/SatukanCinta/dump_main",
    repositories = List(
      Repository(name = "like", kind = "*", facets = List(
        Facet(name = "user", source = "graph", primitive = "node", typeName = "com.satukancinta.domain.User", format = "json"),
        Facet(name = "topic", source = "graph", primitive = "node", typeName = "com.satukancinta.domain.Interest", format = "json"),
        Facet(name = "like", source = "graph", primitive = "relationship", typeName = "LIKE", format = "graphml"))))))) {

Beat that, Java!

Still don't believe me? How about processing a bunch of collections, and sprinkle built-in parallel capability :

    val indexHits = graphDb.getAllNodes.par.filter(_.getProperty("__type__") == typeName)
    log.info("Index for {} returned {} nodes", typeName, indexHits.size)
    val columnNames = indexHits.par.flatMap( node =>
      node.getPropertyKeys.filter( _ != "__type__" ) ).toSet
    val sortedColumns = columnNames.toList.sorted
    log.info("Columns for {}: {}", typeName, sortedColumns.mkString(", "))
    RowMeta(columns = sortedColumns)

I really can't imagine doing that (including the concurrency) in Java. Phew.

Verbose code == easy to read ? Not always. This one is much easier on the eyes.

Tip: To learn more about Scala programming, I recommend Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition.

Wednesday, February 15, 2012

UnproxyableResolutionException Workaround when using Scala Closures and javax.inject CDI Beans Together

Some powerful Scala programming language features like closures, pattern matching, and lazy vals don't work well with dependency injection frameworks like javax.inject aka CDI. This is due to stricter class structure requirements to enable proxying.

For example, this "innocent" code will not work:

  @Inject private var fbPhotoImporterFactory: Instance[FacebookPhotoImporter] = _
  @Produces @Named("facebookPhotoImporter") private var fbPhotoImporter: ActorRef = _

  @PostConstruct
  def init() {
    logger.debug("Starting FacebookPhotoImporter actor")
    fbPhotoImporter = Actor.actorOf(fbPhotoImporterFactory.get())
    fbPhotoImporter.start()
  }

It will throw:

Caused by: org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001437 Normal scoped bean class com.satukancinta.web.Persistence is not proxyable because the type is final or it contains a final method public final javax.enterprise.inject.Instance com.satukancinta.web.Persistence.com$satukancinta$web$Persistence$$fbPhotoImporterFactory() - Managed Bean [class com.satukancinta.web.Persistence] with qualifiers [@Any @Default].
    at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:225)
    at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:178)
    at org.jboss.weld.util.Proxies.getUnproxyableTypesExceptionInt(Proxies.java:193)
    at org.jboss.weld.util.Proxies.getUnproxyableTypesException(Proxies.java:167)
    at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:110)
    at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:126)
    at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:345)
    at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:330)
    at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:366)
    at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:82)
    at org.jboss.as.weld.services.WeldService.start(WeldService.java:89)
    ... 5 more

As you can see, my use code isn't exactly "edge cases".

It's actually a pretty common use case: create a Akka actor and pass a factory function to it, as a closure.
The code above doesn't look like it's using a closure, but it actually is when written like this: (same functionality, but still breaks CDI)

    fbPhotoImporter = Actor.actorOf { fbPhotoImporterFactory.get() }

I can see why CDI has a strict requirement, and I can also understand why Scala implements it the way it is (Scala developers definitely already has a lot of problems working around powerful Scala features into a very restrictive JVM bytecode requirements). This is the price we pay for having a somewhat inferior language (Java, please don't get offended) in the first place.

But I as an application developer want to have a quick fix for this issue. Re-coding the class in plain Java is one option, but it turns I don't need to. There is a workaround, by creating a helper method then using it:

  @Inject private var fbPhotoImporterFactory: Instance[FacebookPhotoImporter] = _
  @Produces @Named("facebookPhotoImporter") private var fbPhotoImporter: ActorRef = _
 
  def createFbPhotoImporter() = fbPhotoImporterFactory.get()
 
  @PostConstruct
  def init() {
    logger.debug("Starting FacebookPhotoImporter actor")
    fbPhotoImporter = Actor.actorOf(createFbPhotoImporter)
    fbPhotoImporter.start()
  }

Now Scala is happy and CDI is also happy. Yes it's a bit more verbose but not too bad. And I guess the code is now somewhat more understandable for Java guys. :)

Tip: To learn more about Scala programming, I recommend Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition.