Thursday, December 18

Want to hear the latest on Guice and OSGi?

Then you'll want to attend EclipseCon 2009, where you can hear me talk about using Guice and the peaberry extension to blend OSGi services with Eclipse extensions:

http://www.eclipsecon.org/2009/sessions?id=315

I'll also be running through some of the design decisions behind peaberry which I think are pretty neat - like the recent work on "outjection" that lets you share services between registries and watch for service updates. If I have time I'll also discuss some thoughts about lifecycle support (for some background see Todor's recent request).

I'm going to be around for the whole conference, so you'll have plenty of opportunities to ask me questions about peaberry, Pax-Construct, the maven-bundle-plugin, or the "OSGi in Action" book :)

Tuesday, December 9

How much OSGi should I use?

This began as a quick reply to a question on the Felix users list about bundling third-party libraries, but these days once I start writing I find it hard to stop! Hope you find it useful...
It's actually up to you - OSGi doesn't force you to make everything a bundle, it merely helps you when you decide to modularize.

So if you want to put third-party libraries on your application classpath and use the "org.osgi.framework.bootdelegation" property to make them visible to all bundles then you can. You could then concentrate on modularizing your application without worrying about legacy classloading issues - however it would also mean you couldn't replace these libraries at runtime, or have multiple versions of them loaded at the same time. Additionally, if you use tools to generate OSGi manifests you'd need to tell them that these packages should not be marked as imported, as they're available instead using bootdelegation - otherwise your bundles would have trouble resolving, because no other bundle would be exporting these packages.

Or you could keep the libraries on your application classpath and use "org.osgi.framework.system.packages.extra" to augment the exports from the main system bundle. Unlike bootdelegation, your bundles would need to import any of these packages they want to use - and these imports would then get wired to the system bundle. However, because you're now using OSGi resolution to find these packages you could replace them at runtime and have other bundles provide alternative versions. The downside is that you may find issues with a few legacy libraries that expect the "classic" model (ie. everything on the application classpath)

Later on you might decide to move libraries from the application classpath into one or more OSGi bundles - you could either crack open the library and add OSGi metadata to the manifest to export everything, or use a tool like BND to create a new jar based on the original. This is great if you want to share libraries between bundles - but if the library is only used by one bundle then it might make more sense to embed the library inside that bundle, especially if it's an implementation detail and you never expect to export any packages. Again you have a choice: you can unpack the library inside your bundle, or embed the jar as-is and add it to your Bundle-ClassPath (OSGi supports "jars within jars").

Once you have the third-party library as (or inside) an OSGi bundle then you can start thinking about making certain packages private, and add a Bundle-Activator to initialize and clean up resources and/or threads. Using an activator is optional and while it will introduce a compile time dependency to OSGi, it doesn't force the library to use OSGi at runtime. You can still use the library in classic Java applications, because they won't attempt to load the activator class. This is cool, because it means you can fully participate in the OSGi lifecycle without affecting anyone not interested in OSGi.

The best part is that you can mix any of these approaches in your application and you can decide when move between them. You're not forced to make everything a bundle, and you may even decide to move bundles back to the application classpath. Feel free to use as much or as little of OSGi as you like :)

Thursday, December 4

Wednesday, November 26

OSGi (Services) in Action

Just noticed that my chapter on OSGi services has reached the Manning Early Access Program. Hope you enjoy reading it, and remember to post any comments or questions on our author forum.

Here's some of the topics covered in Studying Services:
  • The what, why and when of services

  • OSGi services in action!

  • Dealing with dynamics

  • Using services in the paint example

  • How services relate to modularity and lifecycle

  • Framework services

Monday, November 17

Do you remember to unget OSGi services?

Just posted the first set of code examples for OSGi in Action, chapters 1 to 4:

   http://code.google.com/p/osgi-in-action/

The answer to when you should "unget" an OSGi service (and why you should bother) will be explained in chapter 4 of the book, which will hopefully reach Manning's Early Access Program very soon.

Spoiler alert: take a peek at chapter04/dynamics.

Friday, October 24

OSGi in Action!

The kind folks at Manning have just made the first chapter of "OSGi in Action" available through their early access program: http://manning.com/hall/

Unfortunately the figures seem to be chopped off in the PDF, so apologies for that in advance... we're using OpenOffice to write the book and this is apparently new for Manning, so there's still a couple of bugs to squash in the publishing process. Never mind, the next update will be much better!

Richard, Karl and I are eagerly working on getting the next few chapters ready for MEAP. This is where we delve into the different layers of OSGi (modularity, lifecycle and services) with plenty of examples to explain the differences and best practices.

Those of you signed up to MEAP can send comments and corrections via the author forum. You can also reach us via the usual lists (Felix, OPS4J, etc.)

That's all for now - got to get back to writing!

Tuesday, October 14

Karangan - Kampung halaman saya

Nama kampung saya Guarlford. Guarlford terletak dua batu dari sebuah kaki bukit besar yang bernama Malvern Hills. Di sekeliling Guarlford ada banyak ladang, lembu tenusu dan anak biri-biri.

Pada musim bunga pemandangan sangat cantik sebab semua tumbuh-tumbuhan hijau dan segar. Pemandangan musim gugur juga sangat cantik sebab daun-daun pohon menjadi warna-warni.

Walaupun jumlah penduduk di sekitar Malvern adalah tiga puluh ribu orang, jumlah penduduk Guarlford hanya dua ratus lima puluh orang sahaja.

Kampung saya sangat tua, ia wujud sejak tahun 1275. Ibubapa saya dan rakan-rakan mereka telah menulis dua buah buku tentang sejarah Guarlford yang anda dapat beli dari Amazon.

Wednesday, July 30

OSGi Text Scrambling Service

Here's most of the code from the peaberry example I mentioned in my previous post - as you can see, peaberry lets you import and export OSGi services from your Guice enabled application, without introducing a dependency on the OSGi API. In fact you can even plug your own service frameworks into peaberry.

EXPORTING BUNDLE


package examples.scrambler.impl;

import static org.ops4j.peaberry.Peaberry.registration;
import static org.ops4j.peaberry.util.TypeLiterals.export;

import com.google.inject.AbstractModule;
import com.google.inject.Key;

import examples.scrambler.Scramble;

// here's where we bind the exported service...
public class ExportModule extends AbstractModule {

@Override
protected void configure() {
// note: the service is exported at injection time
bind(export(Scramble.class)).toProvider(
registration(Key.get(ScrambleImpl.class)).export());
}
}

package examples.scrambler.impl;

import static com.google.inject.Guice.createInjector;
import static org.ops4j.peaberry.Peaberry.osgiModule;

import org.ops4j.peaberry.Export;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import com.google.inject.Inject;

import examples.scrambler.Scramble;

@SuppressWarnings("unused")
public class Activator implements BundleActivator {

@Inject
final Export<Scramble> handle = null;

public void start(final BundleContext ctx) throws Exception {

// apply the exported service binding
createInjector(osgiModule(ctx), new ExportModule()).injectMembers(this);
}

public void stop(final BundleContext ctx) throws Exception {

if (null != handle) {
handle.remove();
}
}
}


IMPORTING BUNDLE


package examples.scrambler.test;

import static org.ops4j.peaberry.Peaberry.service;

import com.google.inject.AbstractModule;

import examples.scrambler.Scramble;

// here's where we bind the imported service...
public class ImportModule extends AbstractModule {

@Override
protected void configure() {
bind(Scramble.class).toProvider(service(Scramble.class).single());
}
}

package examples.scrambler.test;

import static com.google.inject.Guice.createInjector;
import static org.ops4j.peaberry.Peaberry.osgiModule;

import org.ops4j.peaberry.ServiceUnavailableException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import com.google.inject.Inject;

import examples.scrambler.Scramble;

@SuppressWarnings("unused")
public class Activator implements BundleActivator {

// plain text to be scrambled...
final static String TEXT = "This is a simple test of peaberry.";

@Inject
final Scramble service = null; // Guice can actually inject final fields!

Thread tester;

public void start(final BundleContext ctx) throws Exception {

// apply the imported service binding
createInjector(osgiModule(ctx), new ImportModule()).injectMembers(this);

// quick'n'dirty test thread
tester = new Thread(new Runnable() {
public void run() {
// support cooperative cancellation
while (Thread.currentThread() == tester) {
try {
System.out.println('[' + service.process(TEXT) + ']');
} catch (final ServiceUnavailableException e) {
System.err.println("No scrambler service!");
}
try {
Thread.sleep(2000);
} catch (final InterruptedException e) {
// wake-up
}
}
}
});

tester.start();
}

public void stop(final BundleContext ctx) throws Exception {

// cooperatively stop the thread
final Thread zombie = tester;
tester = null;
zombie.join();
}
}

peaberry 1.0 alpha

You may have noticed I recently uploaded an alpha build of peaberry 1.0

http://peaberry.googlecode.com/files/peaberry-1.0-alpha.zip

today I've also been working on updating the design and user guide pages:

http://code.google.com/p/peaberry/wiki/UserGuide
http://code.google.com/p/peaberry/wiki/DetailedDesign

including a small Eclipse/PDE example I put together in a matter of minutes.
(and which hopefully also works ok on other people's installations of Eclipse!)

http://peaberry.googlecode.com/files/PeaberryExample.zip

At this point I'm feeling good about the API and (unless I hear otherwise) will
concentrate on more "behind-the-scenes" work, and perhaps add a few more
utilities to help developers.

So... if you find any bugs please let me know via the issues tab :)

Tuesday, July 29

IdentityHashMap is broken in IBM JDK 5!

So there I was, happily running some tests with the latest copy of Guice when blam - I got a NullPointerException from inside the injector. Hmmm, I thought, perhaps the latest trunk code is unstable. So I pulled down a stable snapshot... and got the same exception.

Looked at location of the NPE and got even more confused:

   CreationTimeMemberInjector.java:87

where it iterates over the cached entry set of an identity hash-map. Added some debug code, and yes - the entry set is valid to begin with, but after stashing it in a list, the list elements are all null. Weird!

Why hadn't I seen this before, I've run the same test many times - then it struck me, today I happened to have JAVA_HOME set to the IBM JDK, while previously I've used the default Sun JDK.

Time to crack open the src.jar from the IBM JDK - lo and behold in IdentityHashMap.java:1142

public T[] toArray(T[] a) {
return (T[])toArray(); // !!!!
}

that is plain wrong - the specification for toArray(T[] a) clearly states that the provided array must be used if it's large enough:

Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array. If the collection fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this collection.

this behaviour is relied on in other classes from java.util, where they create a large enough array and use c.toArray(elements); to initialize the array contents. Hence the null array when creating a list based on the entry set.

I was going to report this on the "IBM Java Runtimes and SDKs" forum as the problem still exists in the latest service release, but it appears to be offline today! For those interested, here is a simple testcase to recreate the bug:

import java.util.*;

public class IdentityHashMapTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Map map1 = new HashMap();
Map map2 = new IdentityHashMap();
map1.put("Hello", "World");
map2.put("Hello", "World");
System.out.println("MAP 1 : " + map1.entrySet());
System.out.println("MAP 2 : " + map2.entrySet());
System.out.println("LIST 1 : " + new ArrayList(map1.entrySet()));
System.out.println("LIST 2 : " + new ArrayList(map2.entrySet()));
}
}

BTW, that comment // !!!! is actually in the original source code, which suggests someone out there knows this is wrong but couldn't be bothered to fix it...

Friday, June 27

Guice 2.0 and OSGi

Some cool news: the Guice trunk (which will eventually become 2.0) now includes my patches to support OSGi-style classloading, and also adds OSGi metadata to its jars.

This means that you will be able to take the Guice 2.0 jar and drop it onto any OSGi framework, without having to worry about classloading issues wrt. the internal proxy code. The new code also allows generated proxy classes to be unloaded when they're no longer needed.

So when Guice 2.0 hits the internet, the peaberry project will become a neat little extension library that you can drop alongside the Guice jar to inject OSGi services.

Good stuff! ( no more patches :)

Friday, May 16

Bio-reboot

You may (or may not) have noticed that I haven't been as active as usual on various projects. I've been having stomach issues for the last few months, and after numerous tests the doc decided to "reboot" my stomach by clearing out all the bacteria with antibiotics. He's now started me on probiotics to replace the good bacteria/enzymes (like the ones that help digest milk) that got zapped.

It's going to take a while before things are fully back to normal, and I need to regain about 5kg, but I'm feeling more positive (which is a good sign). The doc did tell me to keep my stress levels down, but that may be difficult when there's so many cool ideas that need implementing ;)

Monday, April 7

peaberry 0.3 available for testing / review

I've uploaded a new peaberry bundle along with early design docs:

http://peaberry.googlecode.com/files/peaberry-0.3.jar
(this also contains the source code under OSGI-OPT)

http://code.google.com/p/peaberry/wiki/DetailedDesign

the new design is much less invasive: you can decide to explicitly
add bindings to services without using the @Service annotation if
you want, and you can even use peaberry to inject services from
other registry based systems (by implementing ServiceRegistry).

There's also a small demo to show it working in practice

http://peaberry.googlecode.com/files/peaberry-0.3-logdemo.zip

although this demo doesn't actually do anything useful ;)

I'll upload the user guide tomorrow and then start working on a
production quality implementation of the OSGiServiceRegistry
(the current one is basic proof-of-concept and non-optimal).

Other TODOs:

mandatory services (ie. bundle won't start without them)

service registration (need to find an intuitive approach)

Anyway, please take a look and let me know what you think.

Friday, March 7

A jolt of Guice

Fantastic news from this year's Jolt Awards: Guice won the award for "Libraries/Frameworks" beating several other worthy finalists, including the Spring Framework! Hopefully this news will provoke a fresh injection of interest in Guice :)

Certainly I'm feeling more of a buzz about the next release, and can't wait to find time to continue my work on extending Guice to support dynamic injection of services from registries, such as the one in OSGi (http://code.google.com/p/peaberry).

So congratulations to Bob, Kevin and everyone else involved with Guice!

Pax Construct 1.0 released

I've released version 1.0 of Pax Construct, just in time for EclipseCon! (phew) And now you can find the scripts and plugin on the central Maven repository, so it's even easier to use:

http://repo1.maven.org/maven2/org/ops4j/pax/construct/scripts/1.0/scripts-1.0.zip

Improvement

[PAXCONSTRUCT-66]
- Add all Maven compilation dependencies to the Eclipse classpath

[PAXCONSTRUCT-67]
- Add pax:provision option to select Pax-Runner profiles (-Ddeploy=...)

[PAXCONSTRUCT-68]
- Support use of Pax-Runner argument files (-Dargs=)

[PAXCONSTRUCT-69]
- Support pax:run as alias for pax:provision

[PAXCONSTRUCT-70]
- Provide a pax-provision script that works outside of a Maven project

[PAXCONSTRUCT-71]
- Support provisioning of bundles not marked as provided dependencies

New Feature

[PAXCONSTRUCT-72]
- Add new command "pax-create-module" to simplify creation of subdirectories

Task

[PAXCONSTRUCT-59]
- Look into using velocity instead of groovy to generate the various scripts

Plus several changes to the underlying internals to improve performance and usability.

Tuesday, January 22

maven-bundle-plugin 1.2.0 released

It's finally here, a new stable release of the bundleplugin:


<plugin>
<groupid>org.apache.felix</groupid>
<artifactid>maven-bundle-plugin</artifactid>
<version>1.2.0</version>
</plugin>

hopefully the next development cycle won't take so long :)