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 :)