Showing posts with label ant. Show all posts
Showing posts with label ant. Show all posts

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.