Bringing Scala into the Java EE Space
Merging Scala and CDI using SBT
JAXConf will take place in San Jose next month, and as part of the conference, co-founder of the Albuquerque Java User's Group in Albuquerque, Daniel Hinojosa will present his 'Functional Programming in Scala with CDI' case study, in which he will look at merging the Scala programming language with CDI. In this article, Daniel Hinojosa gives us a taster of what to expect from his JAXconf session, as he looks at getting a CDI implementation to work with SBT.
There is no denying that Scala is a new language to be reckoned with. With more developers trying and settling on the language, it can't be ignored. Given the new circumstances we have an important question – "How well does Scala work in the new Java EE space, if at all?" At JAX 2011 in San Jose, I will be presenting a case study entitled "Functional Programming in Scala with CDI". My aim is to merge these two technologies which have essentially been incubated in their own ecosystems, and publish the results.
Some of the issues I want to investigate:
1. How purely functional can you operate in CDI?
2. Can you inject reuseable functions with ease in CDI?
3. Is there hindrance in using Scala with Mojarra JSF and AJAX frameworks?
4. Do functional design patterns work in the CDI environment?
5. Can integration and acceptance testing in Scala + CDI +Arquillian be used with popular Scala testing frameworks like ScalaTest, Specs, and ScalaCheck?
6. Can a CDI implementation work with SBT (Simple Build Tool) and how will it compare to Maven?
7. Do Scala structures like implicit work in CDI?
This article will describe line item 6, and I am happy to report that it has been successful.
What is SBT?
Simple Build Tool (SBT for short) is a Scala-based build system, completely developed in Scala. SBT has an extremely low learning curve to set up and configure. It is an Ant, Maven, Buildr competitor used exclusively for Java and Scala projects. SBT comes included with all the major testing frameworks and tools, including the ones we will be covering in this article. SBT has an embedded Scala console, supports multiple projects, and has an extensible plug-in architecture. SBT currently has some initial support for IDEA, Eclipse, TextMate, Emacs, and VIM. Since SBT is fairly new, you may still find that there will be some work involved in getting it integrated with your favorite editor or IDE. See the resources below for SBT integration support.
Creating Your Project
Creating a project in SBT is just a simple matter of creating an empty directory that will house your new project and running the sbt command then answering a few questions about your project. Listing 1 shows what a typical initialization will look like.
SBT uses the same folder conventions as Maven. As you can see from Figure 1, all Scala source code is placed in the src/main/scala directory, and all Java source code in the src/main/java directory.
The directory src/main/resources is a folder in which you can place any files that your code relies on: property files, XML files, images, etc. Since this is a web application, all web specific files go into the webapp directory including WEB-INF configuration files.
Defining a Project
Unlike Ant or Maven that use an XML file to configure your build, configuration in SBT is done using an actual Scala class. The Scala class should be placed in the project/build directory inside your project folder and the class must extend the DefaultWebProject class for any SBT web application. In the included example, I created a file called CDIScalaProject.scala and placed it in the project/build directory. You can call the Scala build file whatever you want, as long as the class inherits DefaultWebProject for a web project or DefaultProject for a standard non-web application.
For our example we are going to be using CDI with Scala using Seam 3. Seam 3 is the latest release of the Seam Framework and is thus far the most mature CDI based web framework to date. Its CDI implementation uses Weld. Listing 2 shows a completed project file with the dependencies required for this article and project.
The first line contains the required imports for the Project. The class declaration itself is much like Java with some slight differences. In Line 2, CDIScalaProject class receives a ProjectInfo parameter named info. In Scala, one difference in declaring variables and parameters is that the declarations are reversed; the name of the variable comes before the class type. Therefore in line 2, CDIScalaProject has one parameter, info of the type ProjectInfo. The extends keyword works much like in Java in that it declares that CDIScalaProject will inherit from DefaultWebProject. The difference between Java and Scala is that we specify in our extends clause which parental constructor will get the call based on the parameter signature. In the CDIScalaProject example, it is the constructor that accepts a ProjectInfo object.
In Line 3, 4, and 5 of Listing 2, our CDIScalaProject declares that dependencies can be found in the Scala-Tools Maven2 Repository and the JBoss Maven 2 Repository.
Each remote repository is located at a particular web address. For those unfamiliar with Maven repositories, Maven Repositories are sites that maintain a library of dependencies and their sources. Maven repositories come in either the remote or local varieties.
Remote repositories are Internet or network based repositories that contain the library that will be downloaded by your build tool, in our case, SBT. Local repositories are repositories that contain cached dependencies from remote repositories previously downloaded, critical dependencies not found elsewhere, and in-house projects that have not been published.
Lines 7 through 20 show the dependency requirements for our project. Each repository indexes a dependency by its Maven vector which consists of groupID, artifactID, and version. You can think of a Maven vector like an address to locate a resource within a Maven repository.
For example, in line 10 of Listing 2, SBT will get the seamservlet library, version "3.0.0.CR3", which is listed under the group ID org.jboss.seam.servlet. The library vector is delimited by a '%' and the intent is to make it feel like the slash directory that you are familiar with in your shell. The method, withSources(),will tell SBT to download the source jar files along with the compiled jar library.
Each dependency line can also specify how the library is to be included in the final package, in our case, our war file. Lines 7 through 10 are dependencies marked as "compile" which will be included in the war file. Lines 12 through 15 are dependencies marked as "test" which will only be available when testing production code. Lines 17 through 20 are dependencies marked "provided" which will be available for compiling and testing but not for packaging since these libraries are already provided by our application server. Finally, Lines 23 and 24 are a workaround for SBT so that they do not include source jar files into the final war product.
- What is SBT?
- Running SBT, an Introduction