Thursday, July 3, 2008
OSGi management tool mToolkit free edition released
mToolkit extends the Eclipse IDE with the necessary tools for easier adoption of the OSGi technology. It provides the developers with remote management capabilities of OSGi containers (currently Equinox and ProSyst's mBedded Server are supported). From within the Eclipse IDE the developer can execute bundle operations like installing bundles on a remote OSGi container. Additionally, mToolkit enables access to the OSGi service registry in order to validate the bundle's service dependencies and registrations.
Screenshot of the Eclipse plugin in action:
http://dz.prosyst.com/extra/rr/mToolkit.jpg
For the integration of ProSyst’s mBedded Server Professional and Equinox Edition, mToolkit supports the creation of framework specific launch configurations to e.g. define security parameters and lazy initialization properties.
Please take a look at the following screencasts for feature demonstration and usage instructions.
mToolkit OSGi Remote Management:
https://dz.prosyst.com/step-by-step/mToolkit/mBSManagementDemo.htm
mToolkit mBS Framework Launcher:
https://dz.prosyst.com/step-by-step/mToolkit/FWLauncherDemo.htm
The Eclipse plugin and the necessary bundles for the target OSGi container can be downloaded at:
http://dz.prosyst.com/oss/
Sunday, March 2, 2008
Creating a Domain Specific Language for OSGi
Whereas Scala is probably the most interesting language, the OSGi Technology provides a good candidate for the best framework within the Java system ;-) So what would be more obvious than looking at a combination of them? Of course, since Scala generates Java byte code and the OSGi framework is dedicated to Java this is already possible. Neil Bartlett wrote a nice introduction on how to build an OSGi bundle in Scala.
However, we can do even better! The Scala language syntax provides several mechanisms to create a domain specific language. Lets start with a simple bundle activator written in Scala:
class MyBundleActivator extends BundleActivator {
def start(context: BundleContext) {}
def stop(context: BundleContext) {}
}
Nothing special here. Now lets assume we have the following definitions of a service interface and implementation:
trait SuperService {
def msg: String
}
class SuperServiceImpl extends SuperService {
def msg = "My super message!"
}
To add an instance of the service implementation to the service registry we normally would write:
context.registerService(classOf[SuperService].getName, new SuperServiceImpl,
null)
But with some work and leveraging the syntactic elements of Scala, we can write:
context service classOf[SuperService] add new SuperServiceImpl
This doesn't save a lot of typing but is already much more readable. A nice side effect is, that the compiler ensures that the implementation is a subclass of the interface. So this statement would not compile:
context service classOf[SuperService] add new String("A fake super service")
Using this kind of syntax really pays off if we want to access a service:
context service classOf[SuperService] get {s =>
println(s.msg)
}
Again, the compiler ensures that everything is correctly typed. Thanks to the type inference mechanism, we do not need to declare that the type of variable s is SuperService. So we can directly call s.msg and pass it to the println methods. If we would have tried to call a nonexistent method, e.g. msg2, the compiler would have thrown an error. The Java equivalent to the above code is:
ServiceReference ref = context.getServiceReference(SuperService.class);
if (ref != null) {
SuperService s = (SuperService) context.getService(ref);
System.out.prinln(s.msg);
context.ungetService(ref);
}
While the DSL version is much more readable and less error-prone, it also has the advantage of following the RAII design pattern. We do not need to do the null-check and the DSL library ensures to "unget" the service.
So how does this work? First, lets remove some of Scala's syntactic sugar: In Scala, a method that only has one parameter can also be used as an infix operator. So
obj.method(parameter)
can be used as
obj method parameter
If we reverse this rule to the DSL version for using a service we get
The get method is a higher-order function that passes the reference to the service to a closure. You might find this in future versions of Java (BGGA, CICE, FCM, C3S). More interesting however, is the context.service(...) part of the statement. context is an instance of the BundleContext class that clearly does not have a service(...) method. The trick here is to use an implicit conversion from BundleContext to RichBundleContext. The RichBundleContext has the method service(...) which in turn returns an instance of the class ServiceInformation. This class provides the add and get methods:
context.service(classOf[SuperService]).get({s =>
println(s.msg)
})
class RichBundleContext(context: BundleContext) {
def service[T](s: Class[T]) = new ServiceInformation[T](context, s)
}
class ServiceInformation[T](...) {
def add(...) = ...
def get(...) = ...
}
To convert the BundleContext instance to an RichBundleContext we could either use the constructor directly or we could use a factory method:
// constructor
new RichBundleContext(context).service(classOf[SuperService]).get({s =>
println(s.msg)})
// factory method
implicit def bc2rbc(bc: BundleContext): RichBundleContext = {
new RichBundleContext(bc)
}
bc2rbc(context).service(classOf[SuperService]).get({s => println(s.msg)})
You may have noticed that the bc2rbc method is marked "implicit". So as long as this method is in the local scope (e.g. imported) and "implicit", Scala will automatically apply this method. So context.service(...) automatically becomes bc2rbc(context).service(...). Several conditions must match to make this happen. Please take a look at the Scala documentation for more informations.
There are several use-cases for a custom DSL in OSGi:
// sending events
context event "APP/TOPIC" send new MyEvent(...) // Version 1
context event "APP/TOPIC" ! new MyEvent(...) // Version 2
// receiving events
// Version 1
context event "APP/TOPIC" receive match {
case MyEvent(e) => ...
case _ => ...
}
// Version 2
context event "APP/TOPIC" ? match {
case MyEvent(e) => ...
case _ => ...
}
// Wire admin
context wire classOf[MyType] connect new MyReciever
What do you think? Which cases would you like to see covered by a DSL?
Saturday, February 16, 2008
Fun with OSGi
However, maybe someone should tell EA about OSGi since the author of this blog discover an interesting new use case ;-)
Friday, February 15, 2008
A Comparison of OSGi and Android
Last year, the Open Handset Alliance announced Android, a platform specially targeted at mobile devices. Due to the support from Google, Android received a lot of attention in the community. However, one of the hottest technologies for 2008 is OSGi, a technology rooted in the embedded world.
While OSGi recently got a lot of momentum in Enterprise Java, it is used in embedded devices for years. Like Android, it adds a sophisticated component model, class loader improvements and well-defined management capabilities. In 2006, Release 4 of OSGi was published, which includes support for mobile phones and other handheld devices. This resulted in JSR-232, a component platform for mobile devices.
Gábor Pécsy, Co-Chair of the OSGi Mobile Expert Group and one of the key persons behind JSR-232, published an interesting comparison of OSGi and Android.
What do you think? What are your experiences with OSGi or Android?