Home > Development, Java, JavaFX, programming, Scala > ScalaFX, Scala Build Tool and JavaFX 2.0 Libraries

ScalaFX, Scala Build Tool and JavaFX 2.0 Libraries

November 8th, 2011

Hard Reference

In my last blog entry, ScalaFX A Walkthrough, I talked about setting up ScalaFX 2.0 in IntelliJ 10.5 with the Scala Build Tool (SBT) in the screencast. I left out some salient points.

The JavaFX 2.0 SDK has one important hardcoded reference in it, which makes it hard to use in a Maven or Ivy repository. The reference is in a class called NativeLibLoader and it attempts to initialise the native library with a fixed path. The actually call is something like this:

      AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
          NativeLibLoader.loadLibrary("mat");
          return null;
        }
      });

 

The NativeLibLoader class JavaFX 2.0 expects to find native libraries in the “/../bin” of the class path that references jfxrt.jar.

In order, to get a around the problem you need to manually copy all of JavaFX 2.0 native libraries (*.DLL files) to SBT folders as well.

First, create the directory:

cd scalafx
mkdir lib_managed\jars\com.oracle\bin

 
Note: SBT uses Apache Ivy underneath the hood, hence the peculiar non-Maven group name “com.oracle” as the pathname.

Then, copy the native libraries over:

copy “%JAVAFX_HOME%”\rt\bin\*.dll   lib_managed\jars\com.oracle\bin

 

After this fix for the missing native library, you can build the ScalaFX library successfully using SBT:

 sbt
> compile
> test
> run
> exit

 

Finally, in order to generate a JAR file, you then execute sbt thus:

sbt package
sbt clean compile test package

 

Look in the folder "target" for "scalafx-1.0.jar.

Here are some of the SBT fragments that I added to my version the build.sbt file that will help you get configured:

// Upgraded the latest Scala version from 2.9.0.1 to 2.9.1
scalaVersion := "2.9.1"

// Harded code my local repository, because the following breaks Windows file resolution
// resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
resolvers += "Local Maven Repository" at "file:///Users/Peter/.m2/repository"

// UPGRADE to JAVAFX 2.0 Final Candidate Status (FCS)
libraryDependencies ++= Seq(
    "com.oracle" % "javafx-runtime" % "2.0"
)

// Everyone should using Java 1.6 by now shouldn't they?
javacOptions ++= Seq("-source", "1.6", "-target", "1.6")

// Reduce the JVM heap space for my laptop!
javaOptions += "-Xmx384M"

// Change the JAVA home to something on your system, if required
// javaHome := Some(file("/Library/Java/JavaVirtualMachines/1.6.0_24-b07-330.jdk/Contents/Home"))
javaHome := Some(file("/Program Files/Java/jdk1.6.0_29" ))

 
In order to install the JAR into a local Maven Repository, you need to add the following stanza to the build.sbt file. Again, this is not portable as it directly reflects my machine and my user space.

// Set publish Maven for local repository
publishMavenStyle := true
// Set up the Maven repository
publishTo := Some(Resolver.file("file",  new File( "/Users/Peter/.m2/repository" )) )

 
Now, you can run the SBT command “publish” like so:

> sbt publish 
[info]  published scalafx to C:/Users/Peter/.m2/repository/org/scalafx/scalafx/1.0/scalafx-1.0.pom
[info]  published scalafx to C:/Users/Peter/.m2/repository/org/scalafx/scalafx/1.0/scalafx-1.0.jar
[info]  published scalafx to C:/Users/Peter/.m2/repository/org/scalafx/scalafx/1.0/scalafx-1.0-sources.jar

 
As you can see this is the equivalent of invoking mvn install:install-file almost.

If you want to install to a local Apache Ivy then use the SBT command “publish-local” instead.

> sbt publish-local
[info]  published scalafx to C:\Users\peter\.ivy2/local/org.scalafx/scalafx/1.0/poms/scalafx.pom
[info]  published scalafx to C:\Users\peter\.ivy2/local/org.scalafx/scalafx/1.0/jars/scalafx.jar
[info]  published scalafx to C:\Users\peter\.ivy2/local/org.scalafx/scalafx/1.0/srcs/scalafx-sources.jar
[info]  published ivy to C:\Users\peter\.ivy2/local/org.scalafx/scalafx/1.0/ivys/ivy.xml

 

Please let me know, if you have any more problems. Thanks.
 

IntelliJ and SBT

There was a definite bug in SBT Plug-in for IntelliJ IDEA that prevents the command line input working more than once. I explained this in the video screencast. However, It has been fixed recently, so make sure you update this plug-in to get the fix.

 

Proposal

This copying of manuals DLL is a real pain for Maven / Ivy / SBT developers, because we have do this every single project. I believe Oracle could standardise on the actualise “platform” name (e.g. “Win”, “Mac”, “Solaris”, “Linux”) for the actual loading or come up with a way of making the mechanism indirect. Let me make myself abundantly clear:

// This SBT stanza will not work!!! It is just for illustration
libraryDependencies ++= Seq(
  "com.oracle" % "javafx" % "2.0" % "provided" ,
  ( 
  "com.oracle" % "javafx-windows" % "2.0" % "provided" |
  "com.oracle" % "javafx-macosx" % "2.0" % "provided" |
  "com.oracle" % "javafx-solaris" % "2.0" % "provided" |
  "com.oracle" % "javafx-linux" % "2.0" % "provided" )
}

Therefore Linux native libraries (*.so file) would in a known repository folder and of course you create a POM or IVY file and these entries:

~/.m2/repository/com/oracle/javafx-linux

We know that genuine differences exists in OS and CPU architecture and even chip hardware and therefore we should be sensitive to native changes e.g. Windows 32 versus 64 bit and AMD/Intel then may be schema could like this:

libraryDependencies ++= Seq(
  "com.oracle" % "javafx" % "2.0" % "provided" ,
  "com.oracle" % "javafx-${PLATFORM}[-${VERSION}][-${ARCHITECTURE}][-${CHIPSET}]" % "2.0" % "provided" 
}
// PLATFORM is "windows" and VERSION is "" or "7" or "8"
// and ARCHITECTURE is "" or "32bit" or "64bit"
// and also CHIPSET is "" or "Intel" or "AMD"

I would be very interested in your thoughts on this scheme above. Thank you in advance.

Categories: Development, Java, JavaFX, programming, Scala Tags:
Comments are closed.