Showing posts with label Scala. Show all posts
Showing posts with label Scala. Show all posts

Saturday, February 23, 2013

Using Eclipse and sbt in Scala Programming

This is a tutorial on using the Eclipse IDE and the sbt build tool in Scala programming.

Eclipse is the most popular IDE in Java programming. It is also a great IDE in Scala programming. sbt is the default build tool for Scala projects, like Maven for Java projects. sbt brings the following benefits (among others):
  • Easy management of third-party libraries (inside and outside Eclipse)
  • Easy execution of all tests
  • Easy packaging of artifacts
Eclipse's built-in third-party library management is inconvenient. My other article discussed this issue.

This tutorial teaches how to use Eclipse and sbt together. It is assumed that the readers are Windows users.

Download and Install Eclipse

Download Eclipse Classic 4.2.1. Unzip it to a directory in your PC file system. That is all about Eclipse installation. To start Eclipse, double click eclipse.exe (it is under the eclipse directory).

Create an Eclipse workspace Directory

Simply create an ordinary directory, for example, C:\eclipse-4.2-workspace. Eclipse workspaces are major version specific. It means that you cannot use the same workspace with Eclipse 3.6 and 3.7. 3.6 and 3.7 are two different major versions. On the other hand, it is OK to use the same workspace for both 3.6.1 and 3.6.2. They are two different minor versions, but are still of the same major version (i.e. 3.6). For this reason, I like to put the Eclipse major version number in my workspace names.

Start Eclipse in the Workspace

Start Eclipse. When asked to select a workspace, select the desired workspace directory, e.g. C:\eclipse-4.2-workspace.

Install the Scala-IDE plugin

Scala-IDE is a plugin in Eclipse to develop Scala projects. To install it, with an Eclipse IDE started, click the Help menu and the Install New Software... menu item. On the Install dialog, click the Add button. On the Add Repository dialog, put in "Scala IDE" for the name field, and http://download.scala-ide.org/sdk/e38/scala210/dev/site/ for the location field.

 It will enable Eclipse to work with Scala 2.10.0.

Download and Install sbt

Download sbt.zip and unzip it to your file system. Add the bin directory to your path environment variable.

Add sbteclipse to sbt

sbteclipse is a plugin in sbt to work with Eclipse. Go to the .sbt/plugins directory under your home directory, e.g. C:\Users\ted (for Windows 7). If the directory does not exist, create it. Find a file named plugins.sbt. If it does not exist, create it. Add the following line into it:

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.1")

It will add the sbteclipse plugin version 2.1.1 into sbt.

Create a sbt Project

Under C:\learning, create a directory usesbt. It will be the project base directory. Under the usesbt directory, create a text file build.sbt, with the following content:

name := "SBT Learning"

version := "1.0"

scalaVersion := "2.10.0"

libraryDependencies += "joda-time" % "joda-time" % "2.1" withSources()

libraryDependencies += "org.joda" % "joda-convert" % "1.2" withSources()

Note that there is a blank line between any two code lines.

For people unfamiliar with SBT, here is detailed explanation:

name := "SBT Learning"  - The name of this project is "SBT Learning
version := "1.0" - The project version is 1.0
scalaVersion := "2.10.0" - This project uses Scala version 2.10.0
libraryDependencies += "joda-time" % "joda-time" % "2.1" withSources() -  to add a third-party library joda-time (groupId: joda-time, artifactId: joda-time, version: 2.1)  to our project. SBT will also download the source code for joda-time 2.1 to our local cache (located under ${USER-HOME}\.ivy2, where ${USER-HOME} is a place holder for the user's home directory, e.g. C:\users\ted, on a Windows 7 PC)
libraryDependencies += "org.joda" % "joda-convert" % "1.2" withSources() - to add a third-party library joda-convert (groupId: org.joda, artifiactId: joda-convert, version: 1.2) to our project. joda-convert 1.2 is required for Scala programs that use joda-time 2.1.

Open a command window, cd into the usesbt directory. Run command sbt. You will see the following command output:

[info] Loading global plugins from C:\Users\ted\.sbt\plugins
[info] Set current project to SBT Learning (in build file:/C:/learning/usesbt/)
>

The > shows that you are in the sbt interactive shell.

In the sbt shell, run command eclipse. You will see something like below in the command window:

> eclipse
[info] About to create Eclipse project files for your project(s).
[info] Updating {file:/C:/learning/usesbt/}default-1d1d75...
[info] Resolving org.scala-lang#scala-library;2.10.0 ...
[info] Resolving joda-time#joda-time;2.1 ...

[info] Resolving org.joda#joda-convert;1.2 ...
[info] downloading http://repo1.maven.org/maven2/joda-time/joda-time/2.1/joda-time-2.1-sources.jar ...
[info]  [SUCCESSFUL ] joda-time#joda-time;2.1!joda-time.jar(src) (2730ms)
[info] downloading http://repo1.maven.org/maven2/joda-time/joda-time/2.1/joda-time-2.1.jar ...
[info]  [SUCCESSFUL ] joda-time#joda-time;2.1!joda-time.jar (2309ms)

[info] downloading http://repo1.maven.org/maven2/org/joda/joda-convert/1.2/joda-convert-1.2.jar ...
[info]  [SUCCESSFUL ] org.joda#joda-convert;1.2!joda-convert.jar (296ms)
[info] downloading http://repo1.maven.org/maven2/org/joda/joda-convert/1.2/joda-convert-1.2-sources.jar ...
[info]  [SUCCESSFUL ] org.joda#joda-convert;1.2!joda-convert.jar(src) (608ms)

[info] Done updating.
[info] Successfully created Eclipse project files for project(s):
[info] SBT Learning
>


Import a sbt Project into Eclipse


Now back to Eclipse. Click the File | Import... meu item.

On the Import dialog, select General | Existing Projects into Workspace. Click the Next button. Select C:\learning\usesbt as the root directory. Click the Finish button. 

Now you have a corresponding Eclipse project in the IDE. And you are ready to program in Eclipse.

Programming in Eclipse

Switch to the Scala perspective.

Create a simple Scala program that uses joda-time as in Listing-1.


Listing-1 - A Simple Scala Program
 
package jodatime.example

import org.joda.time.DateTime

object UseJodaTime extends App {  
    println(new DateTime)
}

To run the Scala program, open it on the Editor; right click the editor and, from the context menu, select Run As | Scala Application. The program will run, and output something like:

2013-02-24T15:58:15.228-05:00

Updating Third-Party Libraries

When you need to add/remove/update third-party libraries, change the build.sbt file. Then in the sbt interactive shell, run command reload and eclipse. At last, in Eclipse, right click the project in Package Explorer, and click Refresh from the context menu.

Attach Third-Party Library Source

If you want to look into the source code of or debug through a third-party library, you need to attach its source code to the library. To attach the source code of the joda-time library, do the following:

  1. On Eclipse Package Explorer, right click the SBT Learning project, and from the context menu, select Properties.
  2. On the Properties for SBT Learning dialog, select Java Build Path from the left pane, and the Libraries tab on the right. Select the Source attachment node under joda-time-2.1.jar, click the Edit ... button. See Figure 1 Attach Library Source Code below
  3. On the Source Attachment Configuration dialog, select the External Location radio button, and click the External File button, browse the file system to select ${USER-HOME}\.ivy2\cache\joda-time\joda-time\srcs\joda-time-2.1-sources,jar, where ${USER-HOME} is a place holder for the user's home directory. ...and click the OK button. See Figure 2 Select The Path to The Source Code below.
Figure 1 Attach Library Source Code
Figure 2 Select The Path to The Source Code

Sunday, December 30, 2012

A Issue with Using db4o in Scala Programs

In the other article I showed that we can use db4o in Scala programs. I also mentioned that there are some limitations: db4o cannot correctly store Scala objects with fields of the type scala.collection.mutable.Map and scala.collection.mutable.Set. This article discuss this issue in detail.

The Scala class Programmer (Listing-1) has a field named skillMap whose type is scalca.collection.mutable.Map. The map is used to record the programmer's skills and respective skill levels.

Listing-1 

package tutorial.db4o

class Programmer (val name: String, var phone: String) {
    private val skillMap = scala.collection.mutable.Map[String, Int]()
    
    def skills = skillMap.keySet
    
    def hasSkill(skill : String) = skills.contains(skill)
    
    def skillLevel(skill: String) : Option[Int] = {
        if (hasSkill(skill)) Some(skillMap(skill))
        else None
    }
    
    def addSkill(skill: String, level: Int) {skillMap(skill) = level}
}

In the program in Listing-2, we create an instance of the Programmer class and store it in the db4o database. In the program in Listin-3, we retrieve the object stored in db4o, and print out the programer's name, phone number, skills and corresponding levels. However, the execution runs into an exception.

Listing-2 - A Program to store an object into db4o

package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._

object AddProgrammers extends App {
    // a connection to the tutorial (db4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // create a Programmer instance and store it in the database
    
    val steve = new Programmer("Steve", "513-206-3276")
    steve.addSkill("Java", 6)
    steve.addSkill("Perl", 3)
    connection.store(steve)
    
    connection.commit()
    
    connection.close()
}

Listing-3 - A Program to retrieve an object from db4o

package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._
import com.db4o.query.Predicate

object ReadProgrammers extends App {
    // a connection to the tutorial (db4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // Retrieve programmers with the name Steve from the database
    val rs = connection.query{programmer: Programmer => programmer.name == "Steve"}
        
    // Print out each programmer's name, phone number, and skills
    rs.foreach{programmer =>
        println("Programmer name: %s, phone number: %s, skills:".format(programmer.name, programmer.phone))
        programmer.skills.foreach{skill => println("    %s at level %d".format(skill, programmer.skillLevel(skill).get))}
    }
    
    connection.close()
}

Output of execution of the program in Listing-3:

Programmer name: Steve, phone number: 513-206-3276, skills: Exception in thread "main" java.lang.NullPointerException at scala.collection.mutable.HashTable$$anon$1.(HashTable.scala:159) at scala.collection.mutable.HashTable$class.entriesIterator(HashTable.scala:157) at scala.collection.mutable.HashMap.entriesIterator(HashMap.scala:45) at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:190) at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:45) at scala.collection.mutable.HashMap$$anon$1.foreach(HashMap.scala:99) at tutorial.db4o.ReadProgrammers$$anonfun$2.apply(ReadProgrammers.scala:17) at tutorial.db4o.ReadProgrammers$$anonfun$2.apply(ReadProgrammers.scala:15) at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) at scala.collection.immutable.List.foreach(List.scala:76) at tutorial.db4o.ReadProgrammers$delayedInit$body.apply(ReadProgrammers.scala:15) at scala.Function0$class.apply$mcV$sp(Function0.scala:34) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:60) at scala.App$$anonfun$main$1.apply(App.scala:60) at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59) at scala.collection.immutable.List.foreach(List.scala:76) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:30) at scala.App$class.main(App.scala:60) at tutorial.db4o.ReadProgrammers$.main(ReadProgrammers.scala:7) at tutorial.db4o.ReadProgrammers.main(ReadProgrammers.scala)

Clearly, the Programmer object was not stored correctly in db4o. If we replace the Scala Map by a Java Map (e.g. java.util.HashMap), the programs will work correctly. It is however a awkward work-around to use Java map instead of Scala map in a Scala program.

Sunday, December 23, 2012

Using db4o in Scala Programs

This is a tutorial on using db4o in Scala programs. db4o is an object database management system with both Java and .NET APIs. We can also use db4o in Scala programs (with some limitations) as shown in this tutorial. Scala has many advantages over Java, as also shown in this tutorial. The readers of this tutorial are not assumed to have any knowledge about db4o. However, readers who have experience with Java programs using db4o can appreciate the elegance of Scala over Java more. The readers are expected to have basic knowledge about both Java and Scala programming.

It is a good practice to manage library dependency using Maven. (If you use Eclipse, and are interested in using Maven to manage classpath in Eclipse, you may be interested in this article of mine on this subject.) To manage db4o library dependency using Maven, include the snapshot repository below in the pom.xml file:

<repository>
    <snapshots>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
        <checksumPolicy>fail</checksumPolicy>
    </snapshots>
    <id>db4o</id>
    <name>DB4O</name>
    <url>http://source.db4o.com/maven</url>
    <layout>default</layout>
</repository>

Also include the following dependency on the db4o-full-java5.jar in the pom.xml:

<dependency>
    <groupId>com.db4o</groupId>
    <artifactId>db4o-full-java5</artifactId>
    <version>8.0-SNAPSHOT</version>
</dependency>

(This tutorial includes both Java and Scala programs. If you use Eclipse and want help on working with Eclipse projects mixing Java and Scala, you may be interested in this article of mine on this subject.)

A Java Program Using db4o 

This tutorial starts with a Java program using db4o, to highlight the advantages of Scala. In Listing 2, the Java program opens a db4o database and retrieves Programmer objects with name "Joe" from it. The Java class Programmer is in Listing 1. A programmer has a name and a phone number. The name is not mutable and the phone number is. The query is awkward because a Java method cannot take another method as parameter so we have to wrap the match method in an anonymous class extending the  Predicate class (Line 12 - 17). The shortcoming can be overcome in Scala programs since Scala is also a functional programming language and can take a function as function parameter.


Listing 1 - The Programmer Java Class 

package tutorial.db4o.java;

public class Programmer {
    private String name;
    public String phone;
    
    public Programmer(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }
    
    public String getName() {
        return name;
    }
}

Listing 2 - A Java Program Using db4o 

package tutorial.db4o.java;

import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;

public class ReadProgrammer {
    public static void main(String[] args) {
        ObjectContainer connection = Db4oEmbedded.openFile("tutorial.db4o");
        
        ObjectSet<Programmer> rs = connection.query(new Predicate<Programmer>() {
            @Override
            public boolean match(Programmer programmer) {
                return programmer.getName().equals("Joe");
            }
        });

    }
}

Adding Scala Objects into db4o 

Now let's look into the Scala world. In Listing 3 is the Scala counterpart of the Java Programmer class. An instance of the Scala class Programmer also has a immutable name and a mutable phone number. It is obvious that the Scala version is much simpler.

Listing 3 - The Scala Class Programmer 

package tutorial.db4o

class Programmer (val name: String, var phone: String)

In Listing 4 is a Scala program that creates three instances of the Programmer class and adds them into the db4o database. A Java version will be similar. There is no advantage in Scala programs over their Java counterparts in regard to storing objects into a db4o database, and deleting them from it.

Listing 4 - Add Objects into a db4o Database
 
package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._

object AddProgrammers extends App {
    // a connection to the tutorial (DB4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // create three Programmer instances and store them in the database
    connection.store(new Programmer("Steve", "513-206-3276"))
    connection.store(new Programmer("Bob", "513-376-2521"))
    connection.store(new Programmer("Joe", "513-536-8093"))
    connection.commit()
    
    connection.close()
}

Retrieving Objects from db4o

In Listing 5 is a Scala program that retrieves all programmer instances in the db4o database and prints out their name and phone number. Contrast this program with the one in Listing 2, we can see that the query in the Scala version (Line 11) is much simpler than their Java counterpart (Line 12 - 17). The query method in the Scala version takes an anonymous function as its parameter. The anonymous function, on its turn, takes a Programmer object as its parameter and returns a Boolean value. If it returns true, the programmer object will be included in the query results, or excluded from it if it returns false. In Listing 5, the anonymous function always returns true regardless the programmer object passed in since we want to retrieve all programmer objects in the db4o database.

Listing 5 - Retrieve Objects from a db4o Database 
 
package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._

object ReadProgrammers extends App {
    // a connection to the tutorial (db4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // Retrieve all programmers from the database
    val rs = connection.query{programmer: Programmer => true}
    
    // Print out each programmer's name and phone number
    rs.foreach{programmer =>
        println("Programmer name: %s, phone number: %s".format(programmer.name, programmer.phone))
    }
    
    connection.close()
}

If we run the program in Listing 5 without running the program in Listing 4 before, it prints nothing, because there is no programmer object in the database. If we run the program in Listing 4, then run the program in Listing 5, it will print:

Programmer name: Joe, phone number: 513-536-8093
Programmer name: Bob, phone number: 513-376-2521
Programmer name: Steve, phone number: 513-206-3276

Updating Objects in db4o

In Listing 6 is a Scala program that at first retrieves programmer objects with name "Joe" from the db4o database, and changes their phone number from whatever to 513-111-1111.  

Listing 6 - Update Objects in a db4o Database

package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._

object UpdateProgrammers extends App {
    // a connection to the tutorial (db4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // Retrieve programmers with name "Joe" from the database
    val rs = connection.query{programmer: Programmer => programmer.name == "Joe"}
    
    // Change the programs' phone number
    rs.foreach{programmer =>
        programmer.phone = "513-111-1111"
        connection.store(programmer)
    }
    connection.commit()
    
    connection.close()
}
After we run this program, if we run the program in Listing 5 again, the output will be:

Programmer name: Joe, phone number: 513-111-1111 
Programmer name: Bob, phone number: 513-376-2521 
Programmer name: Steve, phone number: 513-206-3276 

We can see phone number of Joe has been updated.

In db4o, the method to store a brand new object and the method to store a updated object is exactly the same one.

Deleting Objects from db4o 

In Listing 7 is a Scala program that deletes every programmer objects in the database.

Listing 7 - Delete Objects from a db4o Database 

package tutorial.db4o

import com.db4o.Db4oEmbedded
import Adapter._

object DeleteProgrammers extends App {
    // a connection to the tutorial (db4o) database
    val connection = Db4oEmbedded.openFile("tutorial.db4o")
    
    // Retrieve all programmers from the database
    val rs = connection.query{programmer: Programmer => true}
    
    // delete every programmers
    rs.foreach{programmer =>
        connection.delete(programmer)
    }
    connection.commit()
    
    connection.close()
}

The Adapter

The magic to simplify the query method is an adapter class shown in Listing 8.  It is this class that has the query method that takes a predicate (i.e. a function returning a Boolean value) rather than an anonymous class extending the Predicate class. In the company object we also defined a implicit method that converts (i.e. wraps) an ObjectContainer into an Adapter object. With this implicit method, and a import statement import Adapter._, we will be able to call the new version of query method on an ObjectContainer object, as shown in Listing 5, 6, 7 (The compiler will do the conversion behind the scene). These are the real power of the Scala programming language.

Listing 8 - An Adapter Class

package tutorial.db4o

import com.db4o.ObjectContainer
import com.db4o.query.Predicate

class Adapter (connection: ObjectContainer) {
    def query[T](predicate: T => Boolean) : List[T] = {
        var results : List[T] = List[T]()
        val objectSet = connection.query(new Predicate[T]() {
            override
            def `match`(entry: T) = {
                predicate(entry)
            }
        });
        
        while (objectSet.hasNext()) {
            results = objectSet.next :: results
        }
        
        results
    }
}

object Adapter {
    implicit def objectContainer2Adapter(connection: ObjectContainer) = new Adapter(connection)
}

Conclusion 

We can use db4o in Scala programs. The functional programming nature of Scala greatly simplifies the query API. There are, however, some limitations on storing Scala objects in db4o databases. My experience shows that db4o does not support Scala collections. In other words, if a Scala class has Scala Map and Set as fields, db4o will not be able to store them correctly. I am going to discuss more details in this regard in my next post on this subject.

Sunday, October 14, 2012

Deploying Scala Desktop Applications via Java Web Start

[Last update on 04/08/2013]

Java Web Start is a great technology to deploy Java applications. It can be used to deploy Scala applications as well. This tutorial shows how to do it.

The Example Application

Our example Scala application is a simple Scala Swing desktop GUI, shown as Listing 1. Compile it and package the produced class files in a jar file. Let's name the jar file scala-gui.jar. To compile and run it, we need two scala libraries: scala-library and scala-swing. In this tutorial, we use scala-library-2.9.2.jar and scala-swing-2.9.2.jar.

Listing 1 - The Example Application

package simple.scala.swing.gui

import scala.swing._

object HelloWorld extends SimpleGUIApplication {
    def top = new MainFrame {
        title = "Scala Swing"
        contents = new Label {
            text = "Hello World!"
        }
    }
}

When runs, the application shows a simple window with text "Hello World!" as its content, as in the figure below.

Figure 1 - Example Scala Application


Host Web Server

To deploy the Scala application via Java Web Start, we have to host it on a web server. In this tutorial, we use Tomcat as our web server.

In Tomcat, create a simple web application named scala-gui. The figure below shows the directory structure of the Tomcat home directory.

Figure 2 - Directory Structure of Tomcat Home





Library Jar Files

Sign scala-gui.jar, scala-library-2.9.2.jar, and scala-swing-2.9.2.jar with a private key. (If need, see the appendix later for the how-to). Copy the above three jar files to webapps/scala-gui/lib under the Tomcat home directory.

jnlp Files

Create two jnlp files - scala-gui.jnlp and lib.jnlp, and place them under webapps/scala-gui under the Tomcate home directory. Content of the two jnlp files are in Listing 2 & 3. The IP of our web server is 192.168.241.128.

Listing 2 - scala-gui.jnlp

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+"
    codebase="http://192.168.241.128/scala-gui/"
    href="scala-gui.jnlp">
    <information>
          <title>Scala GUI</title>
          <vendor>xxx</vendor>
          <homepage href="http://192.168.241.128/scala-gui/" />
          <description>A simple Scala Swing GUI application to demo Web Start Deployment</description>
    </information>

    <security>
        <all-permissions />
    </security>

    <resources>
        <jar href="lib/scala-gui.jar" />
        <extension href="lib.jnlp"/>
    </resources>
    
    <application-desc main-class="simple.scala.swing.gui.HelloWorld" />
</jnlp>
 
 
Listing 3 - lib.jnlp 

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+"
    codebase="http://192.168.241.128/scala-gui/"
    href="lib.jnlp">
    <information>
          <title>Scala GUI Library</title>
          <vendor>scala.org</vendor>
          <homepage href="http://192.168.241.128/scala-gui/" />
          <description>Scala language and Swing libraries</description>
    </information>

    <security>
        <all-permissions />
    </security>
    
    <resources>
        <jar href="lib/scala-library-2.9.2.jar" />
    </resources>
    
    <resources>
        <jar href="lib/scala-swing-2.9.2.jar" />
    </resources>

    <component-desc/>
</jnlp>

The Web Page 

Finally, create our web page for users to download the Scala application. It is a simple HTML file, as shown in Listing 4.  

Listing 4 - index.html 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Scala GUI</title>
        
        <script src="http://www.java.com/js/deployJava.js"></script>
    </head>
    
    <body>
      <H1>Scala GUI</H1>
  
  Click this button to start the Scala GUI:
  <script>
                 var url = "http://192.168.241.128/scala-gui/scala-gui.jnlp";
          deployJava.createWebStartLaunchButtonEx(url, '1.7.0');
  </script>
    </body>
</html>


The web page will be shown in a web browser as in the figure below.

Figure 3 - Download Page of the Applicatio

When a user click the Launch button on the web page, if Java Web Start has been installed on the client machine, a dialog as in the figure below will be shown to the user.

Figure 4 - Open JNLP with Java Web Start


If the user takes the default option, i.e. "Open with Java(TM) Web Start Launcher", a Security Warning dialog will be shown next, as in Figure 5. It is because we signed the jar files with a self-signed certificate. If we had signed the jar files with a certificate signed by a certificate authority trusted by the user, there would not be such warning. If the user accept the unverified signature, Java Web Start will download the Scala application and run it on the user's machine, as shown in Figure 1.

Figure 5 - Security Warning

Troubleshooting

Java Web Start may log/trace many useful information that can be used to troubleshoot deployment problems.

To enable Java Web Start log/trace on a Windows machine, do the following:

  1. Go to the Control Panel, and click the Java Control Panel. On the Java Control Panel dialog, choose the Advanced tab. Under Setting / Debugging, check both Enable tracing and Enable logging, as shown in Figure 6.
  2. Find the deployment.properties file. (On a Windows 7 machine, it is under C:\users\${username}\AppData\LocalLow\Sun\Java\Deployment, where ${username} should be replaced by concrete username.) Make sure the deployment.properties file has the following configuration lines:
    • deployment.trace=true
    • deployment.trace.level=all

Figure 6 - Java Control Panel    





On a Windows 7 machine, the log and trace files can be found under C:\users\${username}\AppData\LocalLow\Sun\Java\Deployment\log.




Appendix - Using Java keytool & jarsigner


Generate Keys

The example below shows how to generate keys using Java keytool.

keytool -genkey -alias tedkey -keypass tedpass -dname "cn=Ted Gao, ou=, o=, l=Mason, s=Ohio, c=US" -keystore C:\web-start-tutorial\ted.keystore -storepass tedpass -validity 1825 -keyalg RSA -keysize 2048 -storetype JCEKS -v

The command above has to be in one line. It generates a pair of RSA private key and certificate with 2048 bit strength, and stores them in a keystore file named ted.keystore under C:\web-start-tutorial. Alias for this key pair is "tedkey". The alias is to be used to specify which key (pair) to use later. The keystore and the private key are protected with a password "tedpass". The password for the private key is required to read the private key; the password for the keystore is required to write to the keystore. They do not have to be the same password. In this example, we just use the same password for both.

Sign  Jars

The example below shows how to sign java files using Java jarsigner.

jarsigner -keystore C:\web-start-tutorial\ted.keystore -storepass tedpass -keypass tedpass -storetype JCEKS -verbose scala-gui.jar tedkey

The command above has to be in one line. It use a keystore named ted.keystore under C:\web-start-tutorial. Alias of the key to use is "tedkey". Both the private key and the keystore are protected by password "tedpass". The example above signs a jar file named scala-gui.jar.

Thursday, May 31, 2012

Exception Handling in Scala

For exception handling, both Scala and Java have similar try/catch/finally constructs.  In addition, exception handling in Scala can be done using the various member classes of the scala.util.control.Exception object, such as Catch, Try, Catcher, and Finally, in stead of the try/catch/finally construct. In this tutorial, we are going to see examples of both approaches.

try/catch/finally Construct

There is a small difference between Scala and Java's try/catch/finally constructs. In Java, one may have multiple catch clauses for a single try clause, each for a exception class (the Exception class itself or its subclass). In Scala, only one catch clause is needed, and multiple cases are used to handle multiple exception classes. Listing 1 below illustrate such exception handling in Scala.

Listing 1 - Example Using the try/catch/finally Construct

package exception.handling.examples

import scala.io.Source
import java.io.IOException
import java.io.FileNotFoundException

object TryClauseExample extends App {
    val fileName = "c:\\temp\\test.txt"
     
    val content =
    try {
        Source.fromFile(fileName).getLines.mkString("\n")
    } catch {
          case e: FileNotFoundException => throw new SystemError(e)
          case e: IOException => throw new SystemError(e)
    }
    
    println(content)
}

In Listing 1, the simple program reads a file from the file system, store the file content in a variable named content, and print content's value to the console. If a FileNotFoundException, or a more general IOException occurs, it wraps the exception into a custom excepton named SystemError (see Listing 2) and throws the SystemError exception. Since FileNotFoundException is not treated in any way different from the more general IOException, one case will be sufficient. We used two cases in the example just to show how to handle different Exception subclasses.

Listing 2 - SystemError

package exception.handling.examples

class SystemError(message: String, nestedException: Throwable) extends Exception(message, nestedException) {
    def this() = this("", null)
    
    def this(message: String) = this(message, null)
    
    def this(nestedException : Throwable) = this("", nestedException)
}

scala.util.control.Exception object and its Member Classes

It is not necessary to use the try/catch/finally construct to handle exceptions. The same thing can be done using various methods and nested classes of the singleton object scala.util.control.Exception. In this tutorial, we are just going to refer to this singleton object as the Exception singleton. The program in Listing 3 is equivalent to the program in Listing 1, but does not use the try/catch/finally construct.

Listing 3 - First Example Using the Catch Class 

package exception.handling.examples

import scala.util.control.Exception.catching
import java.io.IOException
import java.io.FileNotFoundException
import scala.io.Source

object CatchClassExample1 extends App {
    val fileName = "c:\\temp\\test.txt"
        
    val fileCatch = catching(classOf[FileNotFoundException], classOf[IOException]).withApply(e => throw new SystemError(e))
    
    val content = fileCatch{Source.fromFile(fileName).getLines.mkString("\n")}
    
    println(content)
}

The most important thing about the Exception singleton is its (nested) member class Catch. Every object of this class captures the exception handling logic usually captured by the catch (and optionally the finally) part of a try/catch/finally statement. In general, such exception logic are about:
  1. What exception, e.g. FileNotFoundException and IOException, to catch
  2. What to do when catching each of those exceptions, e.g. wrapping the exception in another exception and throwing the later, 
  3. Optionally, what to do always no mater whether an exception occurred or not, i.e. the body of a finally clause in a try/catch/finally statement
The Exception singleton has a method whose header is

catching[T](exceptions: Class[_]*): Catch[T]

 

This method returns a Catch object. The method parameter exceptions are the exception classes to be caught by the Catch object. In our example (Line 11 of Listing 3), calling the catching method and passing to it two exception classes (i.e. FileNotFoundException and IOException) returns a Catch object that will catch FileNotFoundException and IOException.

The Catch class has a method withApply, whose header is

withApply[U](f: (Throwable) ⇒ U): Catch[U] 

 

Calling this method on a Catch object will return another Catch object that will execute the anonymous function passed as argument to the withApply method, when a target exception is caught. In our example (Line 11 of Listing 3), variable fileCatch references a Catch object that will catch FileNotFoundException and IOException, and will throw a custom exception - SystemError - that wraps the caught exception.

The Catch class has a method apply, whose header is

apply[U >: T](body: ⇒ U): U

 

Calling the apply method, passing a code block as argument to the method, will execute the code block, like the case of a try clause in a try/catch/finally statement. If that code block throw any exception targeted by the Catch object, the Catch object will catch the exception and execute another code block - the one passed to it via calling its withApply method.

This explains why the two programs in Listing 3 and Listing 1 are equivalent.

Listing 4 - Second Example Using the Catch Class 

package exception.handling.examples

import scala.util.control.Exception.catching
import java.io.IOException
import java.io.FileNotFoundException
import scala.io.Source

object CatchClassExample1 extends App {
    val fileName = "c:\\temp\\test.txt"
        
    val fileCatch = catching(classOf[FileNotFoundException], classOf[IOException]).withApply(e => throw new SystemError(e))
    
    val content = fileCatch.opt{Source.fromFile(fileName).getLines.mkString("\n")}
    
    println(content.getOrElse("The file cannot be found or read"))
}

Listing 4 is slightly different from Listing 5. In Line 13, instead of the apply method, the opt method, of the Catch object is called. The opt method, like the apply method, takes a code block as parameter, and executes the code block. If calling the apply method with a certain code block as argument returns normally, i.e. not throwing exception, calling the opt method with the same code block as argument will return a Some object wrapping that normal result; if calling the apply method with a certain code block as argument throws an exception, calling the opt method with the same code block as argument will return None. The program in Listing 4 will print the file content to the console if the file can be found and read. If the file cannot be found or read, it will print string "The file cannot be found or read" to the console.


Listing 5 - Third Example Using the Catch Class 

package exception.handling.examples

import scala.util.control.Exception.catching
import java.io.IOException
import java.io.FileNotFoundException
import scala.io.Source

object CatchClassExample1 extends App {
    val fileName = "c:\\temp\\test.txt"
        
    val fileCatch = catching(classOf[FileNotFoundException], classOf[IOException]).withApply(e => throw new SystemError(e))
    
    val content = fileCatch.either{Source.fromFile(fileName).getLines.mkString("\n")}
    
    println(content.right.getOrElse("The file cannot be found or read"))
}

Listing 5 is also slightly different from Listing 3. In Line 13, instead of the apply method, the either method, of the Catch object is called. The either method, like the apply method, takes a code block as parameter, and executes the code block. If calling the apply method with a certain code block as argument returns normally, i.e. not throwing exception, calling the either method with the same code block as argument will return a Right object wrapping that normal result; if calling the apply method with a certain code block as argument throws an exception, calling the either method with the same code block as argument will return a Left object wrapping the exception. The program in Listing 5 will print the file content to the console if the file can be found and read. If the file cannot be found or read, it will print string "The file cannot be found or read" to the console.

Conclusion
 The exception handling with the Catch class has two advantages comparing with the traditional try/catch/finally construct approach:
  1. reusing exception handling logic. That is "Don't Repeat Yourself". A Catch object captures a certain exception handling logic. One can call the apply (or opt, or either) on the same Catch object many times, each time with different argument - code block equivalent to the body of a try clause. In the case of the try/catch/finally construct approach, when there are multiple try/catch/finally statements only differ in the try clause, the catch and finally clause still has to be duplicated for each try clause.
  2. Supporting Monad, with the opt and either methods of the Catch class
 The exception handling with the Catch class also has two disadvantages comparing with the traditional try/catch/finally construct approach:
  1. Unfamiliar to a large body of programmers, while almost every programmer with basic knowledge of Object-Oriented programming is familiar with the try/catch/finally construct.
  2. Scattering the exception handling logic about what exceptions to catch, what to do when catch them, and the code that throws those exception into different location in source code.When the gaps between those locations are large, likely the logic will be more difficult to understand than other wise. 
The first disadvantage can be overcome with a little training. In general the second disadvantage cannot be easily overcome. Programmers need to be cautious and weight the costs over benefits while choosing one approach over the other.

Saturday, October 1, 2011

Immutable Objects and val Variables Are Not the Same Thing in Scala

In Scala programs, some objects may be mutable, others immutable. A mutable object's state can be changed. An immutable object's state cannot be changed.

Listing 1 - A Mutable Object

object Example1 extends Application {
    val aList = scala.collection.mutable.Set(1, 2, 3)
    println(aList)
    
    aList.add(4)
    println(aList)
}

In Listing 1, we create a mutable Set object with 3 elements (viz 1, 2, and 3) in it. Then, add a new element, 4, to it. Run the program, it will display:

Set(2, 1, 3)
Set(2, 1, 4, 3)

Obviously, we can change the state of the mutable Set object. If instead, we create an immutable Set object, for example, with the following statement
 
val aList = scala.collection.immutable.Set(1, 2, 3)

We won't be able to add a new element into that Set object. Accordantly, there is not the add method for the immutable Set class. (The + method will create a new Set object rather than add a new element into the original set).

In Scala programs, an variable may be a var or val variable. An variable holds a reference to an object. An var variable can be re-assigned to reference another object. A val variable cannot be re-assigned.


Listing 2 - val Variable Cannot Be Re-Assigned

object Example1 extends Application {
    val aList = scala.collection.mutable.Set(1, 2, 3)
    aList = scala.collection.mutable.Set(1, 2, 3, 4)
}

When we compile the program in Listing 2. Scala compiler will complain: reassigment to val. If we change val to var as in Listing 3, the program will compile fine.

Listing 3 - var Variable Can Be Re-Assigned

object Example1 extends Application {
    var aList = scala.collection.mutable.Set(1, 2, 3)
    aList = scala.collection.mutable.Set(1, 2, 3, 4)
}

Notice that in Listing 1, even aList is a val variable, we can change the state of the object referenced by it since the object is a mutable object.

Even though both immutable and val are about somethings that cannot be changed, one is about the object states, another objects referenced. They are indeed totally different. However, beginner Scala programers may get confused.

Sunday, September 11, 2011

Mixing Scala and Java in a Project, Developed in Eclipse and Built by Maven

(Last updated on February 26, 2012)


 Overview

This is a tutorial showing how to setup a project (aka module) with both Scala and Java source code, to be built by Maven. In addition, this tutorial also shows how to setup the exact project in the Eclipse IDE so that developers can code and compile both Scala and Java source code in the same project.

If you only want to develop a mixed Java/Scala project in Eclipse, and you don't care about to build the project outside Eclipse using Maven and to manage Eclipse build path using Maven, you can do so using the Scala IDE for Eclipse out of box. 

Arguably, the largest advantage of the Java programming language over many other programming languages is the existence of countless libraries in Java.  Scala fully leverages this advantage of Java. Scala is very attractive for on one hand, it is a much more powerful programming language, and on the other hand, a Scala method can call almost any Java method as easy as another Java method does so. A Java method can also easily call a Scala method with certain limitations.

When develop a new project (as the term is used in the Eclipse IDE or the Maven build tool), it may be very desirable to have both Java and Scala classes in it. We may have some developers in the project who can only write Java code. We may also have to write some classes in Java in order to fit into certain frameworks or containers. Under those circumstances, a pure Scala project is not an option. If we still want to take advantage of the power of Scala, we have to mix Scala and Java in the same project. Being able to easily mix Scala and Java in the same project will greatly lower the obstacle for organizations to adopt Scala.

This tutorial is about the tricks in a Maven POM file to enable us to
  • Develop a project with both Scala and Java classes in Eclipse, where some Java methods call Scala methods, and some Scala methods call Java methods.
  • Use Maven to manage project build path in Eclipse
  • Build the project outside Eclipse using Maven
For a discussion on the advantages of using Maven to manage Eclipse project build path, see my other post.

Being able to build the project outside Eclipse using Maven makes it very easy to include that project into a larger project as a sub-project (called a module in Maven) later.

To follow this tutorial, you need:
  1. JDK 1.6 (not JDK 1.7)
  2. Eclipse Classic 3.6.x (not 3.7)
  3. The Scala IDE for Eclipse 2.0. The Scala IDE for Eclipse is an Eclipse plugin. If you need help in installing the plugin, please see the Appendix A at the end of this tutorial.
  4. Maven 2.2.1 or later
 In this tutorial, we develop a Hello World program consisting of:
  1. A Java class, GreetingInJava, with a method greet() which simply prints “Hello World!” to the console. It is normally the only class in a Java Hello World program.
  2. A Scala class GreetingInScala, with a method greet(), which instantiates a GreetingInJava instance, and call its greet() method. This is to show calling a Java method from a Scala method.
  3. A Java class, Bootstrap, with a main() method, in which a GreetingInScala instance is instantiated and the greet() method is called on that instance. This is to show calling a Scala method from a Java method.
Layout the Project

We are going to create the project outside Eclipse and to import it into Eclipse later. For more detailed about creating a project outside Eclipse and importing it into Eclipse, see my other post. Under C:\temp, create a directory structure as below.





Create Maven pom.xml

Create a pom.xml file under C:\temp\hello with the following content:



<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/maven-v4_0_0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>ted-gao</groupId>
    <artifactId>scala-java-mix</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Scala-Java mixture</name>
    <description>Showcase mixing Scala and Java</description>
    <packaging>jar</packaging>
    
    <build>
        <plugins>
            <!-- ensure that we use JDK 1.6 -->
            <plugin>
                <inherited>true</inherited>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <!-- Run scala compiler in the process-resources phase, so that dependencies on
                         scala classes can be resolved later in the (Java) compile phase -->
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>                        
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        </execution>

                        <!-- Run scala compiler in the process-test-resources phase, so that dependencies on
                             scala classes can be resolved later in the (Java) test-compile phase -->                    
                        <execution>
                        <id>scala-test-compile</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <!-- Add src/main/scala to source path of Eclipse -->
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/main/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                      
                    <!-- Add src/test/scala to test source path of Eclipse -->
                    <execution>
                        <id>add-test-source</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>add-test-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/test/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            
            <!-- to generate Eclipse artifacts for projects mixing Scala and Java -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.8</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                    <projectnatures>
                        <projectnature>org.scala-ide.sdt.core.scalanature</projectnature>
                        <projectnature>org.eclipse.jdt.core.javanature</projectnature>
                    </projectnatures>
                    <buildcommands>
                        <buildcommand>org.scala-ide.sdt.core.scalabuilder</buildcommand>
                    </buildcommands>
                    <classpathContainers>
                        <classpathContainer>org.scala-ide.sdt.launching.SCALA_CONTAINER</classpathContainer>
                        <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
                    </classpathContainers>
                    <excludes>
                        <!-- in Eclipse, use scala-library, scala-compiler from the SCALA_CONTAINER rather than POM <dependency> -->
                        <exclude>org.scala-lang:scala-library</exclude>
                        <exclude>org.scala-lang:scala-compiler</exclude>
                    </excludes>
                    <sourceIncludes>
                        <sourceInclude>**/*.scala</sourceInclude>
                        <sourceInclude>**/*.java</sourceInclude>
                    </sourceIncludes>
                </configuration>
            </plugin>
            
            <!-- When run tests in the test phase, include .java and .scala source files -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.8.1</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                        <include>**/*.scala</include>
                    </includes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>
</project>

It is OK for Java classes/interfaces to depend on Scala classes/objects because Scala classes/objects are compiled before Java classes/interfaces. It is also OK for Scala classes/objects/traits to depend Java classes/interfaces because Scala classes/objects/traits can be compiled against both Java source code and bytecode.


Create Eclipse Artifacts

Run Maven Eclipse plugin to create Eclipse project artifacts and configure the Eclipse workspace with path variable M2-REPO pointing to the local Maven repository. If you need help to do those tasks, please see my other post.

Create Java and Scala Classes

In Eclipse, create the following two Java classes and one Scala class.

GreetingInJava is a simple Java class.

package mix.java.scala;

package mix.java.scala;

public class GreetingInJava {
    public void greet() {
        System.out.println("Hello World!");
    }
}

GreetingInScala is a simple Scala class that calls Java.

package mix.java.scala

class GreetingInScala {
    def greet() {
        val delegate = new GreetingInJava
        delegate.greet()
    }
}

Bootstrap is a simple Java class that calls Scala. If you need help to create new Scala classes in Eclipse, see the Appendix B at the end of this tutorial.

package mix.java.scala;

public class Bootstrap {

    public static void main(String[] args) {
        GreetingInScala scala = new GreetingInScala();
        scala.greet();
    }
}

Run Bootstrap.java in Eclipse

Right click Bootstrap.java in the source editor in Eclipse. From the context menu, select Run As... -> Java Application.

You will see string "Hello World!" is printed to the console.

Build the Project Outside Eclipse, Using Maven

Open a command line window and cd to C:\temp\hello, execute the following command:

mvn install

You will see Maven compile the three Java and Scala classes and package them into a jar file.

Run Bootstrap.java outside Eclipse


Open a command line window and cd to C:\temp\hello, if you have not done so. Execute the following command:


mvn exec:java -Dexec.mainClass=mix.java.scala.Bootstrap

You will see "Hello World!" is printed to the command line window.


Conclusion


With the pow.xml in this tutorial, we will be able to create projects with Java and Scala source code mixed. We will be able to develop both Java and Scala source code in Eclipse. We will also be able to run the Java and Scala classes in Eclipse. We will also be able to build the project and to execute the classes outside Eclipse using Maven.

Appendix A – Installing the Scala IDE for Eclipse

On the Eclipse workbench, select Help -> Install New Software ...



When the Install dialog box appears, click the Add button. When the Add Repository dialog box appears, fill in a name for the plugin and the URL of the update site for the Scala IDE for Eclipse, and click the OK button.


Back to the Install dialog box, check all available plugins as shown on the snapshot below.


When you see the following warning, ignore it and click the OK button.


When the installation is finished, you need to restart Eclipse.

Appendix B – Creating New Scala Class in the Scala IDE for Eclipse

On the Package Explorer view, right click the desired package. From the context menu, select New -> Other… When the New dialog box appears, select Scala Wizards -> Scala Class.

[If you are also interested in developing Scala programs using Eclipse and sbt (instead of Maven) together, please read Using Eclipse and sbt in Scala Programming.]