Thursday, December 28, 2006

More Ant builds

Since the Scala compiler is a pretty heavy process to run in buildfiles where it is not needed, I've nested it within a conditional to only run when the Scala library is in the classpath.

My new build macro looks like this:
    <macrodef name="build">
<attribute name="srcdir"/>
<attribute name="builddir"/>
<sequential>
<mkdir dir="@{builddir}" />
<javac srcdir="@{srcdir}"
destdir="@{builddir}"
source="${compile.source}"
target="${compile.target}"
deprecation="${compile.deprecation}"
debug="${compile.debug}">
<classpath refid="classpath" />
</javac>

<if>
<available classpathref="classpath" classname="scala.ScalaObject"/>
<then>
<scalac srcdir="@{srcdir}"
destdir="@{builddir}"
classpathref="classpath" />
</then>
</if>

<copy todir="@{builddir}">
<fileset dir="@{srcdir}">
<include name="**/*"/>
<exclude name="**/*.java" />
<exclude name="**/*.scala" />
<exclude name="**/.svn/*" />
</fileset>
</copy>
</sequential>
</macrodef>

We also need to define the scalac task like so:
    <taskdef resource="scala/tools/ant/antlib.xml">
<classpath>
<pathelement location="ant/jars/scala-compiler.jar" />
</classpath>
</taskdef>

Wednesday, December 27, 2006

Ant builds

We have a standardized ant build file(s) at work. There is usually not much thinking needed other than naming the project. If we used Scala regularly, we would need to incorporate the <scalac ... /> target into our buildfiles in such a way that it would transparently build Scala code if it existed. It is also important that the build succeed in one pass with no manual intervention for the CI server to perform its automated builds.

How can we structure our code and build files to satisfy this requirement? Scala code and freely call Java code (and vice-versa). In our build files we need to call both javac and scalac in some particular order. If we call javac first, then code like following will fail because the java compiler cannot yet see the scala class when it executes.
--- Foo.java ---
public class Foo {
private Bar bar;
// ...
}

--- Bar.scala ---
class Bar {
// ...
}
Of course, you have the reverse situation if you call scalac first, with same-project Java code invisible to the Scala compiler. A post to the Scala mailing list brought the following suggestion:
--- Foo.java ---
public class Foo {
private Bar bar;
// ...
}

--- Bar.java ---
public interface Bar {
// ...
}

--- BarImpl.scala ---
class BarImpl() extends Bar {
// ...
}

This allows us to statically reference a Java interface from Java code and to implement the class in Scala. Instances can be created at runtime, using the container (EJB, Spring, or JSF) or by using
Class.forName("package.BarImpl").newInstance();

Of course, we can still easily reference our Java object from Scala.
--- Baz.scala ---
class Baz {
def doSomething(foo: Foo): Unit = {
// do something with our Java object Foo
}
def doSomethingElse(): Unit = {
// instantiate our own Java-defined object
foo = new Foo();
}
}

So, the plan is to require Java interfaces for any Scala objects that are referenced from Java code. Of course, many of the advantages from Scala come from using its type system and will only show if whole layers of an application are implemented in Scala. Luckily, most of our layers are hidden behind interfaces anyway.

Next I'd like to experiment with different types of container-instantiation of Scala classes.

Tuesday, December 26, 2006

What next?

My goal is to identify potential problems with using Scala in my work environment. Most apps are small-to-middling sized web applications used internally to support a sales and manufacturing company. Relevant technologies used are:
  • Glassfish for the application server
  • JSF/Facelets for the view layer
  • Eclipse for the IDE. Although there is some attraction for Netbeans.
  • Yes, we still build with Ant. Being a mouth-breather, I can't quite wrap my head around Maven.
  • Continuous Integration. We use Hudson, but I'm more wed to the idea of CI than to any particular server.
My brainstorm list of questions to be answered:
  • Can I build ejb3s with Scala?
  • JSF-managed beans?
  • Spring-managed beans?
  • How do I structure builds with mixed Java/Scala code?
  • Can I use annotations? Create them in Scala?
I'm sure that I'll come up more as I go along.

Monday, December 25, 2006

What I want (for now)

I want to learn more about Scala. I've already read most of the documentation. I even did some hello-world type exercises. But, that is about as far as I can go without trying to apply it to some real-world problems. I don't have any extra time to make up problems to solve, which means I would have to use it in projects at work. Doing so presents a couple of challenges:
  1. Using a new language can be incredibly unproductive (at first) and detrimental to deadlines. I can't afford to bite off too much.
  2. We have a team of 5 developers, and being able to work with each other's code is very important. I would be sorely ticked-off if I had to fix a bug and found myself struggling with some scripting-language-of-the-week.
I intend to use the next few weeks to explore ways to minimize the first challenge. Since Scala compiles to Java bytecode, we should (in theory) be able to gradually incorporate Scala code into our projects where it makes sense and provides some benefits. In practice, there are many issues relating to our environment and the libraries/frameworks/tools that we use that might cause heartburn.

The second challenge is not as straight forward. Personally, I'm interested in learning new concepts and applying them. Scala has many features that make it attractive as an alternate language, especially for Java developers. However, what is interesting to me is not necessarily interesting to other people. Plus, I have a history of chasing interesting but impractical technologies.

But, I figure that exploring the technical challenges can keep me occupied before I try to convince four other people that using Scala is a great idea.