Scala and OSGi using NetBeans
For some reason, I can’t keep OSGi in my head. Everything I read about it slips away in a few weeks, and I have re-read the guides and tutorials.
Here’s a memo of setting up OSGi bundle written in Scala using NetBeans, following Neil Barlett’s OSGi in Practice, except the book uses Eclipse.
Installing Scala on Mac
Skip this section if you use non-Mac. Install MacPorts. Run the following from Terminal:
sudo port install scala-devel
This could take minutes as it downloads the files.
Install RCEnvironment by copying RCEnvironment.prefPane
into /Library/PreferencePanes
. When you open System Preferences, Environment Variables now show up. Set JAVA_HOME
and SCALA_HOME
to where it makes sense. I have them set to /Library/Java/Home/
and /opt/local/share/scala/
.
Installing NetBeans
Download NetBeans. You could pick any edition as long as it has Java SE. Follow the instructions in Scala Plugins for NetBeans 6.8 v1.x (RC1) to install Scala plugin.
Installing a Framework
Download Felix Framework binary package, extract it under some location such as ~/Application/
. The felix directory will be referred to as FELEX_HOME
.
Setting up NetBeans
Open NetBeans. Within NetBeans, open Library Manager (Tools menu → Libraries). Hit New Library… button, and type “ApacheFelix2.1.0” or whatever the version number you are using. Next hit Add JAR/Folder… button and add FELIX_HOME/bin/felix.jar
. I’ve also added some source zip files under Sources section.
Create new Scala project by selecting (File menu → New Project…) and picking Scala Application under Scala folder. Enter the project name OSGiTutorial
and accept all the other default values. This project directory will be referred to as PROJECT_HOME
.
Under Projects tree view, find Libraries node for the newly created project, right-click and select Add Library…. This should pop up a dialog where you can select ApacheFelix1.8.0 and hit Add Library button.
Copy conf/
and bundle/
from FELIX_HOME
to PROJECT_HOME
. If you are using Felix 2.0.1 like I am, you have to modify the conf/config.properties
file to mimic the older behavior of Felix as follows:
Line 61:
#felix.auto.deploy.action=install,start
felix.auto.deploy.action=
Line 72:
#felix.auto.install.1=
felix.auto.start.1= \
file:bundle/org.apache.felix.shell-1.4.1.jar \
file:bundle/org.apache.felix.shell.tui-1.4.1.jar \
file:bundle/org.apache.felix.bundlerepository-1.4.2.jar
Running Felix
Select (Run menu → Set Project Configuration → Customize…) to open the Project Properties. Enter org.apache.felix.main.Main
to be the Main class, and enter
-Dfelix.config.properties=file:conf/config.properties
to be VM options. Now, Felix will start by hitting Run button.
Installing bnd
Download Peter Kriens’s bnd.jar, and put under some location like ~/Application/bnd
. Open Library Manager (Tools menu → Libraries). Hit New Library… button, and type “Bnd.” Next hit Add JAR/Folder… button and add BND_HOME/bnd-0.0.xxx.jar
.
Under Projects tree view, find Libraries node for the newly created project, right-click and select Add Library…. This should pop up a dialog where you can select Bnd and hit Add Library button.
Installing Scala OSGi bundle
Find out the Scala version that’s being used by NetBeans by selecting (Tools menu → Scala Platforms) if you don’t have $SCALA_HOME
set, or by running
$ scala -version
from the Terminal if you have $SCALA_HOME
. In my case it was 2.8.0.Beta1-RC7.
Download Heiko Seeberger’s Scala OSGi bundles. The snapshots are available, so find OSGi bundle of scala-library for the appropriate version, and place them in some folder such as ~/Applications/scala-osgi
. Copy scala-library-2.8.0-20100109.130112-12.jar
into $PROJECT_HOME/bundle/
folder as well.
Hello, World!
Under Projects tree view there should be a node for Source Packages and a package calledosgitutorial
. Right-click and delete Main.scala
. Right-click, select (New → Other...) and select Scala Class under Scala node. Enter HelloWorldActivator
as the name of the file and hit Finish button.
Here’s the code for HelloWorldActivator.scala
:
package osgitutorial
import org.osgi.framework._
class HelloWorldActivator extends BundleActivator {
def start(context: BundleContext) {
println("Hello, World!");
val bundleNames = context.getBundles()
.map(b => b.getSymbolicName())
.filter(b => b != context.getBundle());
println("Installed bundles: " + bundleNames.mkString(", "));
}
def stop(context: BundleContext) {
println("Goodbye, World!");
}
}
Switch to Files tree view next Project tree view on NetBeans. Create helloworld.bnd
by selecting (File menu → New File…), and selecting Empty File under Other. Click Next, type helloworld.bnd
into the file name, and click Finish. Here’s the content for helloworld.bnd
:
# helloworld.bnd
Private-Package: osgitutorial
Bundle-Activator: osgitutorial.HelloWorldActivator
Under Files tree view, open build.xml. This is an Ant build file. Add two targets within the project tags as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project name="OSGi_Tutorial" default="default" basedir=".">
<description>Builds, tests, and runs the project OSGi Tutorial.</description>
<import file="nbproject/build-impl.xml"/>
<target name="bnd-build">
<taskdef name="bnd"
classname="aQute.bnd.ant.BndTask"
classpath="dist/lib/bnd-0.0.337.jar"/>
<bnd
classpath="build/classes"
eclipse="false"
failok="false"
exceptions="true"
files="helloworld.bnd"
output="bundle"/>
</target>
<target name="-post-jar" depends="bnd-build">
</target>
</project>
Now by clicking Build button on NetBeans, OSGi bundle helloworld.jar gets created under bundle/
folder.
Installing the bundles
If you haven't already, hit Run button on NetBeans to start Felix. It should look like the following:init:
deps-jar:
compile:
run:
Welcome to Felix.
=================
->
This is Felix shell, which we could use to install bundles. Type ps
at the prompt and hit return. This will display all active bundles:
-> ps
START LEVEL 1
ID State Level Name
[ 0] [Active ] [ 0] System Bundle (2.0.1)
[ 1] [Active ] [ 1] Apache Felix Shell Service (1.4.1)
[ 2] [Active ] [ 1] Apache Felix Shell TUI (1.4.1)
[ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.4.2)
->
Now type the following command at Felix shell:
install file:bundle/helloworld.jar
This should return
-> install file:bundle/helloworld.jar
Bundle ID: 4
Next, type following command at Felix shell:
start 4
This should return
-> start 4
org.osgi.framework.BundleException: Unresolved constraint in bundle 4: package; (package=scala.runtime)
So helloworld bundle is loaded into Felix, but it’s not able to resolve scala.runtime
package, which makes sense since we haven’t load it yet.
Now type the following command at Felix shell:
install file:bundle/scala-library-2.8.0-20100109.130112-12.jar
This should return
-> install file:bundle/scala-library-2.8.0-20100109.130112-12.jar
Bundle ID: 5
Next type
start 4
again at Felix shell. This should return
-> start 4
Hello, World!
Installed bundles: org.apache.felix.framework, org.apache.felix.shell, org.apache.felix.shell.tui, org.apache.felix.bundlerepository, helloworld, org.scala-lang-osgi.scala-library
Incremental Development
Now that both Build button and Run button are configured, we can try incremental development by updating bundles without shutting down the OSGi container.
Make some changes in HelloWorldActivator.scala
. For example, change “Hello, World!” to “Bonjour le Monde!” Then, hit the Build button to build helloworld.jar
bundle.
Change the Output tab back to OSGi_Tutorial (run) and type stop 4
at Felix shell. This stops the bundle. Next type update 4
at Felix shell. This updates the bundle. Finally by typing start 4
at the shell, we can start the bundle again:
-> stop 4
Goodbye, World!
-> update 4
-> start 4
Bonjour le Monde!
Installed bundles: org.apache.felix.framework, org.apache.felix.shell, org.apache.felix.shell.tui, org.apache.felix.bundlerepository, helloworld, org.scala-lang-osgi.scala-library
In the end
Type shutdown
to shutdown Felix. The installed bundles will stay even after the shutdown. To clear the state, you have to purge PROJECT_HOME/felix-cache/
folder. I merely followed along Neil Barlett’s OSGi in Practice, so most of the credits should go to him.