Scala is a relatively
new language that incorporates features of object-oriented and
functional programming into a strongly typed, fully compiled
language that has the "feel" of a scripting language. Scala
compiles to Java byte codes and the language is designed to
integrate with Java programs and libraries.
Scala incorporates a lot of features that could be useful for
developers writing extensions to NetKernel and NetKernel
applications. To start my investigation of both the language and
its suitability for work with NetKernel I started with a simple
accessor. This posting describes how I got Scala to run on OS X and
work with NetKernel 3.3.
First, the Scala code. The following code implements a simple
accessor in Scala.
import org.ten60.netkernel.layer1.nkf.impl.NKFAccessorImpl
import org.ten60.netkernel.layer1.nkf.INKFConvenienceHelper
import org.ten60.netkernel.layer1.nkf.INKFRequestReadOnly
import org.ten60.netkernel.layer1.representation.StringAspect
class HelloWorld extends NKFAccessorImpl(NKFAccessorImpl.NOT_SAFE_FOR_CONCURRENT_USE, INKFRequestReadOnly.RQT_SOURCE)
{
override def processRequest(context: INKFConvenienceHelper)
{ val message = "Hello World from Scala"
val sa = new StringAspect(message)
val response = context.createResponseFrom(sa)
response.setMimeType("text/plain")
context.setResponse(response)
}
}
Scala import statements look and operate like Java
import statements. Scala classes do not need explicit
constructors, the line starting with class defines the
class name and indicates it extends the Java class
NKFAccessorImpl and calls the superclass
constructor with two parameters.
Overrides of methods must start with the keyword
override. In Scala the combination of functional and
imperative styles can be see when variables are declared. A
var indicates a mutable variable for imperative
programming while a val indicates an immutable value
seen in functional programming. It is natural to use
val for NetKernel code as a fundamental tenet of
resource oriented computing is that all responses contain immutable
representations.
Scala is a fully compiled, type-checked language - however
notice that I do not need to state the type of each of the
val objects (message, sa and
response). This is due to the Scala compiler's ability
to infer types. Scala was designed to minimize the amount of code
typed and to make it have the "look-and-feel" of a scripting
language.
Scala also supports some level automatic type conversion. While
I have not yet investigated it, I believe this feature would allow
me to reduce the accessor method code to:
override def processRequest(context: INKFConvenienceHelper)
{ val response = context.createResponseFrom("Hello World from Scala")
response.setMimeType("text/plain")
context.setResponse(response)
}
As I explore Scala I'll investigate this feature and report on
it and other discoveries I make.
Getting Scala to run and compile on OS X is straight forward. I
run OS X Leopard on a PowerBook G4 but I would imagine Intel Macs
would work just the same. I downloaded
Scala as an IzPack Java installer, ran the installer and placed
Scala at ~/scala. Next I wrote the accessor in a file
HelloWorld.scala in the root directory of a module and
compiled it with the following from the command line.
~/scala/bin/fsc -classpath .:[install]/modules/ext-layer1-1.3.4.jar:[install]/1060netkernel-2.8.4.jar HelloWorld.scala
Note: "[install]" should be replaced by the path to the
directory on your machine where you installed NetKernel and the JAR
file names are for NetKernel 3.3.
I used the fast Scala compiler (fsc) but the regular Scala
compiler (scalac) could be used. The fast Scala compiler installs
an instance of itself in memory and listens on a port for compile
requests. The regular Scala compiler is slower because it starts up
a JRE instance each time it is called.
The compiler creates the file HelloWorld.class that
contains Java byte codes. At this point integrating the Scala
HelloWorld accessor with NetKernel is just like integrating a
compiled Java accessor. Map a logical address to the class with an
entry such as this one from the mapping section of my module's
module.xml file:
<ura>
<match>ffcpl:/helloworld</match>
<class>HelloWorld</class>
</ura>