gary on June 25th, 2009

Trying to start a program created with the eclipse Scala plugin, I saw an error that the main class couldn’t be found. That was cryptic, as there was a main. Stranger still, this is a program I had run successfully before.

The first part of solving the problem was to look for clues in the Problems view. Opening it, I saw this:

error while loading Configgy, Scala signature Configgy has wrong version expected: 5.0 found: 4.1 in /Users/…

So the first error was due to the compilation failing and not producing a main class that eclipse could launch.

After further digging, the version error turned out to be caused by a mismatch between the Scala version (2.7.5) I used to compile the Configgy library and the Scala version (2.8) that the eclipse plugin used to compile the rest of the program. I didn’t install Scala 2.8, so how could this occur? The Scala plugin installs its own version of Scala. Because I had selected the nightly build version of the plugin, the Scala versions drifted apart during one of the eclipse updates.

You can tell which version the eclipse Scala plugin uses by looking at the jar name in the eclipse/plugins directory. Eg, scala.tools.nsc_2.75.final.jar

The solution was to revert to the stable, release version of the plugin. Do that by using this url in the eclipse Software Updates | Available Software | Manage Sites… list.

http://www.scala-lang.org/scala-eclipse-plugin

More complete directions here.


Bookmark and Share

Tags: ,

In NetBeans, creating a runnable jar for your Scala program is even easier. It’s done automatically when you build your project. The compile output even reminds you how to run the jar file.

The first time I did it, I saw an error about finding a Scala object. Solve that by adding the scala-library.jar to your project. Right-click on the libraries folder in the Projects tab on the left sidebar. Choose Add JAR/Folder and find your scala-library.jar. Because I installed Scala with MacPorts, mine was under

/opt/local/var/macports/software/scala/2.7.4_0/opt/local/share/scala/lib

See this blog entry for more on finding MacPorts installations.

Add any other required libaries this way. Rebuild. Then you can run your program via

$ java -jar YourProgram

in the dist/ directory.

Note that by default, the NetBeans jar mechanism creates a jar file for your program and then adds the libraries you specified into a lib directory. So it’s not a single executable jar. You can then zip and distribute the jar/directory. The advantage of this approach is that you can update the libraries in the lib directory without having to rejar everything. You can probably also save space by using symbolic links in the lib directory to point to your jar locations. I haven’t tried that, though.

You can ignore the lib directory by directly linking to your libraries in the java command using Xbootclasspath. Here, I’ve added two libraries, Configgy and the Scala jar, to my project, but note that I also had to include the path to the Java SDK:

java -Xbootclasspath:/opt/local/var/macports/software/scala/2.7.4_0/opt/local/share/scala/lib/scala-library.jar:../configgy/dist/configgy-1.3/configgy-1.3.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Classes/classes.jar -jar ScalaApplication1.jar

If you want to create a single jar with all of the required files, then add a few lines to your build.xml file. There are many varying pages on the web about this; I found these directions simplest:

1. Add

<target name="-pre-jar">
    <unjar dest="${build.classes.dir}" src="${file.reference.theLibraryName.jar}">
</target>

to the build.xml file, replacing theLibraryName with the appropriate jar filename.

2. Rebuild

To get the correct library filename, switch to the Files tab in the left sidebar and look in the project.properties file. Find lines that look like these:

<unjar dest="${build.classes.dir}" src="${file.reference.configgy-1.3.jar}"/>
<unjar dest="${build.classes.dir}" src="${file.reference.scala-library.jar}"/>

You can ls -l your program in the dist directory and see that it’s much larger; it now contains the libraries. The lib directory is still there, but you don’t need it anymore.


Bookmark and Share

Tags: ,

How do you create a single runnable jar that contains all the files it needs to run? This is one of those questions that should be easier to answer. Here’s how to do it in eclipse and NetBeans.

First, eclipse, following the post here:
1. Create a Java class to run your Scala main:

package scala.loader;
import java.util.*;
public class ScalaEntryPoint
{
    public static void main(String[] args) {
    List<string> argList = new ArrayList<string>();
    argList.add("YourScalaObjectWithMain");
    for (String s : args) argList.add(s);
        scala.tools.nsc.MainGenericRunner.main(argList.toArray(new String[0]));
    }
}

Be sure to change YourScalaObjectWithMain to your class. Also, you’ll have to add the Scala tools jar to your projects classpath: Project | Properties | Java Build Path tab | Libraries tab | Add External Jars… button. Then pick the scala.tools.nsc file in your eclipse/plugins folder.

2. Create a Run Configuration to run the Java class. Check that it runs.

3. Then choose File | Export…, then Java | Runnable JAR File, then pick the Java run configuration to export and a destination. Optionally, you can save the ant XML file that does the export. Later, after some edits, you can rejar using

ant -f yourjarXMLfile.xml

If you change your libraries, be sure to repeat the complete Export process to make sure your jar scrips includes the correct jars.


Bookmark and Share

Tags: ,

gary on June 21st, 2009

http://lhorie.blogspot.com/2008/10/hello-world-in-scala-and-jetty.html

Bookmark and Share
gary on June 21st, 2009

http://developer.yahoo.net/blogs/hadoop/2009/06/yahoo_distribution_of_hadoop.html

Bookmark and Share

It’s easy to use and update the git version of Configgy and other code hosted at github. If you don’t have git, you can use MacPorts to install it:

$ sudo port install git

Then clone the Configgy repository with

$ git clone git://github.com/robey/configgy.git

Then cd into the top-level directory and build as described below.

When you want to update, just pull the latest changes and rebuild.

$ git pull
$ ant clean; ant package

Note that ant package may be particular to Configgy. Sometimes just ant is sufficient and will use the defaults.


Bookmark and Share

Tags: ,

gary on June 21st, 2009

Configgy is a great configuration and logging library for Scala. You can read info/examples on the release page or git the current repository.

To install, just download and, in its directory, type

$ant package

( The ‘$’ is your terminal command-line prompt. Don’t type it.)

If you see the following errors:

[scalac] Compiling 16 source files to /Users/Gary/Development/scala/configgy/target/classes
[scalac] /Users/Gary/Development/scala/configgy/src/main/scala/net/lag/configgy/JMXWrapper.scala:51: error: wrong number of arguments for constructor MBeanInfo: (java.lang.String,java.lang.String,Array[javax.management.MBeanAttributeInfo],Array[javax.management.MBeanConstructorInfo],Array[javax.management.MBeanOperationInfo],Array[javax.management.MBeanNotificationInfo])javax.management.MBeanInfo
[scalac] new jmx.MBeanInfo(”net.lag.configgy.ConfigMap”, “configuration node”, node.asJmxAttributes(),
[scalac] ^
[scalac] /Users/Gary/Development/scala/configgy/src/main/scala/net/lag/configgy/JMXWrapper.scala:115: error: value asList is not a member of javax.management.AttributeList
[scalac] for (attr <- jcl.Buffer(attrs.asList)) setAttribute(attr)
[scalac] ^
[scalac] two errors found

…it’s because Configgy requires Java 1.6. You probably haven’t set your JAVA_HOME and are defaulting to Java 1.5. To correct your environment variables on the Mac, see my notes below.

Next, if you’re trying out the example code and see an error like:

Compiling 1 source file to /Users/Gary/Development/NetBeansProjects/ScalaApplication1/build/classes
/Users/Gary/Development/NetBeansProjects/ScalaApplication1/src/scalaapplication1/Main.scala:27: error: value get is not a member of net.lag.configgy.Config
val hostname = config.get(”hostname”, “localhost”)

…it’s because that function has been renamed getString(), but not all of the documentation has been updated. Change it to:

val hostname = config.getString(”hostname”, “localhost”)


Bookmark and Share

Tags:

Nice talk about alternatives to shared-state concurrency on the JVM. Notice the gradual acceptance by the community that shared-state concurrency is too hard to get right and must be abandoned. Alternatives are being sought; this talk discusses STM, Actors, and Dataflow. I also hear more death knells for Java. Due to the required language integration of concurrency paradigms, new languages are needed such as, in this talk, Clojure and Scala. (The Actor example is Scala, as is the Dataflow example.)

http://www.slideshare.net/jboner/state-youre-doing-it-wrong-javaone-2009


Bookmark and Share

Tags:

gary on June 21st, 2009

When working with Java and Scala, you might have to set environment variables. For example, compiling the excellent Configgy for Scala requires Java 1.6. How do you set the environment variables so that Scala programs compile with Java 1.6? It’s easy, but there are some gotchas.

Currently (June 2009), the Mac OS (10.5.7) defaults to Java 1.5. You can change this setting using the Java Preferences program in /Applications/Utilities. Drag 1.6 to the top of the list. Run “java -version” from a command line to see which version the system will use. You should go ahead and switch it to use the latest Java, but you’re not done yet.

The Java Preferences panel affects which version of Java is run, but not which JDK is used. For development, you need the correct Java JDK. Set it via JAVA_HOME.

A simple and oft-recommended way to set JAVA_HOME on the Mac is to point it to “/Library/Java/Home/”. However, this location is for the system’s default, which is currently 1.5.

You want to use 1.6, so point to it directly at

/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home

If you follow that path, you’ll see that there’s also a 1.6.0 directory. But selecting 1.6 means that it will point to the latest 1.6.x version. Use 1.6.0 if you need to specify 1.6.0 specifically.

Now, where to set that variable… Common advice is to set it using a shell export such as

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home

Add that line to your ~/.profile or your ~/.bashrc and you’re done. That will certainly work for any terminal compiling that you do. But it won’t work for programs installed in your /Applications folder that you don’t run from the command line.


To get those applications to ’see’ the environment variable, use the Doug McClure’s free program RCEnvironment. It’s a System Preferences pane that will edit ~/.MacOSX/environment.plist for you. You could just edit the file, but it’s XML, so let RCEnvironment balance the tags for you.

Finally, if you’re using an ant-based build, you can easily see which sdk is being used in the build process by running

$ ant -diagnostics

…and reading the through the output.


Bookmark and Share
gary on June 17th, 2009

The Scala Eclipse plugin is in development, so we can forgive little issues. One I keep running into is that programs sometimes can’t find themselves upon start. On the canonical hello-world program, I see:

Exception in thread “main” java.lang.NoClassDefFoundError: HelloWorld
Caused by: java.lang.ClassNotFoundException: HelloWorld

So far, the only explanation I’ve found from searching the web is that the metadata is horked, so the workspace must be nuked from orbit, that being the only way to be sure. I’ve tried it and it works, but this approach is hardly practical for production coding.


Bookmark and Share

Tags: ,