Tuesday, December 30, 2008

Truth, Technology and People

I'm reading an excellent novel, which was written in 1957, that contains the following interesting quote that caught my eye:
"It is only in the realm of pure science that truth is an absolute criterion. When we deal with applied science, with technology - we deal with people. And when we deal with people, considerations other than truth enter the question."

Wednesday, November 26, 2008

EclipseCon 2009 Submissions

Time is short for EclipseCon 2009 submissions! All submissions must be in by 28th November, so consider submitting something now. In the meantime, check out my submissions:

Wednesday, November 19, 2008

Rough Cuts

Our first Rough Cuts edition of Equinox and OSGi: The Power Behind Eclipse is available online now!

Tuesday, November 18, 2008

OSGi Book in the Works

As you might have heard by now, I'm working with Jeff McAffer and Paul Vanderlei on an OSGi book. The book will be published by Addison-Wesley and will be part of the Eclipse Series. The working title is Equinox and OSGi: The Power Behind Eclipse, and you can even find it listed by Amazon, but the book won't be available until 2009.

The book is firstly an OSGi book, and secondly an Equinox book, and it covers many of the best practices that we have learned from building real-world OSGi applications. The bulk of the book is a tutorial that develops an application as you proceed through the chapters. There's also some deep dive chapters that attempt to discuss more complicated issues in detail.

We've just submitted some chapters to be published online under the Rough Cuts program, so be sure to check it out! There's also a blog dedicated to the book that we intend to update as we get closer to the publication date.

Friday, June 13, 2008

Working with Multiple LogServices

The fact that there can be multiple registered services of a particular type can sometimes be problematic. Consider the LogService and it's cousin the LogReaderService. When there are multiple registered LogService and LogReaderService pairs it can be tricky for an application to be able to present a single view of the application's logged messages.

It is this reason that SAT now has a LogReaderAggregatorService. As its name implies, it aggregates each registered LogReaderService and presents a single service API with which to work with the application's entire log. The LogReaderAggregatorService is straight forward:
public interface LogReaderAggregatorService extends LogReaderService {
public Enumeration/*<LogEntry>*/ getLogInOrder();
public boolean isLoggingToConsole();
public void setLogToConsole(boolean logToConsole);
}
Since the interface extends the OSGi-defined LogReaderService you can use the API you're familiar with, such as getLog(), but of course what you'll get back is an Enumeration of every LogEvent for every registered LogReaderService, in reverse chronological order.

The LogReaderAggregatorService interfaces adds the method getLogInOrder() for accessing every logged message in chronological order, and a couple of methods for controlling whether logged messages will be echoed to the console.

While the LogReaderAggregatorService interface is part of the required bundle org.eclipse.soda.sat.core, the implementation lives in the optional bundle org.eclipse.soda.sat.core.log.

Wednesday, June 11, 2008

Eclipse 3.4 is almost here...

If you've not heard, Ganyemede is coming... Time is running out fast, so please consider downloading Eclipse 3.4RC4 and kicking the tires a little. Likewise, Equinox 3.4RC4 is available too. There is still time to report any bugs you might find.

Wednesday, March 19, 2008

Best Commercial Equinox Application: Cyrano

Congratulations to Band XI on their Best Commercial Equinox Application victory with Cyrano. See all the winners here. Here's a photo of John accepting the award, but where's Brett and Patrick?

Wednesday, March 12, 2008

More Equinox Command Provider Enhacements

The bundle org.eclipse.soda.sat.equinox.console.cmdprov extends the Equinox console by registering four org.eclipse.osgi.framework.console.CommandProvider services.

  • Bundle Dependencies: These commands allow you to query the dependency and prerequisite relationships that exist between bundles.

  • Configuration Admin: These commands allow you to query the ConfigurationAdmin service for configuration PIDs, factory PIDs and configuration properties. This command provider requires a ConfigurationAdminservice to be registered.

  • Logging: These commands let you query and set the log level, and query and control whether tracing is on or off.

  • Missing Imported Services of Bundles and Configurations: These commands allow you to query the missing required and optional imported services of SAT bundles and configurations created by ConfigurationAdmin.

To use the Equinox console, launch the OSGi framework with the -console program argument, which is present by default for an OSGi Framework launch configuration. Typing help at the Equinox console will display the following additional command usage information:

---Bundle Dependencies---
adep - show all dependents of the specified bundle
apre - show all prerequisites of the specified bundle
dep - show dependents the specified bundle
pre - show prerequisites of the specified bundle
---Configuration Admin---
cprops [pid] - display the configuration properties
fpids [filter] - display the factory pids
pids [filter] - display the pids
---Logging---
logLevel [(debug|info|warning|error)] - query and control log level
trace [(on|off)] - query and control tracing
---Missing Imported Services of Bundles and Configurations---
ams [id] - show all missing imported services
mos [id] - show missing optional imported services
mrs [id] - show missing required imported services

Friday, March 7, 2008

SAT Support Proxy Service Equality

Previous posts talked about the problem of comparing the equality of two proxies, and a solution that involves unwrapping each proxy before performing the equality test. Today's post is short and sweet in that it simply shows the code to test SAT's support for proxy equality. The following snippet of code creates a proxied service and compares it with itself.

FactoryUtility utility = FactoryUtility.getInstance();
BundleContext context = getBundleContext();
IProxyServiceHandler handler = new ProxyServiceHandlerAdapter() {
public Object createService() {
return new HotdogVendor();
}
};
IServiceRecord record = utility.createExportProxyServiceRecord(context, VendorService.class, handler, null);
Object service = record.getService();
boolean equal = service.equals(service);
System.out.println("service.equals(service) = " + equal);

The console output is, as follows:

service.equals(service) = true

Thursday, March 6, 2008

Supporting Proxy Equality

Yesterday's post talked about how using the equals(Object) method to compare two Proxy objects always evaluates to false, even when the receiver and the parameter are the same instance. Today's topic is how to implement the InvocationHandler interface such that the equals(Object) method is handled correctly.

The solution is to intercept the invocation of the equals(Object) method and invoke it with an unwrapped receiver and parameter. Here's how...

public class MyInvocationHandler extends Object implements InvocationHandler {
private Object object;

public MyInvocationHandler(Object object) {
super();
this.object = object;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
String name = method.getName();
if (name.equals("equals") && args.length == 1) {
MyInvocationHandler handler = toMyInvocationHandler(args [ 0 ]);
if (handler != null) {
Object[] parameters= new Object[] {
handler.object
};
result = method.invoke(object, parameters);
}
}

if (result == null) {
result = method.invoke(object, args);
}

return result;
}

private MyInvocationHandler toMyInvocationHandler(Object parameter) {
InvocationHandler handler = Proxy.getInvocationHandler(parameter);
boolean valid = handler instanceof MyInvocationHandler;
if (valid == false) return null;
MyInvocationHandler myHandler = (MyInvocationHandler) handler;
return myHandler;
}
}

Rather than anonymously implementing the InvocationHandler interface, we have the class MyInvocationHandler. The object field is used to store the object that is being proxied.

We must intercept the invocation of the equals(Object) method, and where the parameter is an instance of MyInvocationHandler, we must invoke the Method, passing as a parameter the MyInvocationHandler instance's object field.

This technique of unwrapping the parameter Proxy only works when the proxy is one that has an invocation handler that is an instance of MyInvocationHandler. In cases where the parameter is not an appropriate proxy, execute continues as normal in the invocation handler.

Wednesday, March 5, 2008

Question: When is an object not equal to itself?

Most developers would agree that the expression object.equal(object) aways evaluates to true, and I thought so too until a short while ago where I found that it can sometimes evaluate to false. Trust me, it can happen. Consider the following code:
  public interface IPerson {
//...
};

private class Person extends Object implements IPerson {
//...
};
The Person class inherits its equals(Object) method from Object, the implementation of which is:
  public boolean equals (Object object) {
return this == object;
}
So if the expression object == object always evaluates to true, and yes, it always evaluates to true, how could it be possible for the expression object.equals(object) to ever evaluate to false?

Answer: When it's a proxy. This is a serious problem, since in most cases where proxies are used the fact that you're using a Proxy should not be something you need to think about. Consider the following code that creates a proxy and then compares it with itself:
  final IPerson person = new Person();

ClassLoader classLoader = Person.class.getClassLoader();
Class[] interfaces = {
IPerson.class
};
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(person, args);
}
};
Object object = Proxy.newProxyInstance(classLoader, interfaces, handler);

boolean equal = object.equals(object);
System.out.println("object.equals(object): " + equal);

boolean identical = object == object;
System.out.println("object == object: " + identical);
This code outputs the following to the console:
  object.equals(object): false
object == object: true
When I first saw this I could not believe my eyes, thinking that it must be a bug in either the JVM or the implementation of the Proxy class, when of course it was neither. The problem lies in the anonymous inner-class implementation of the InvocationHandler interface:
  InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(person, args);
}
};
The receiver is always a Proxy, so when we evaluate object.equals(object), execution quickly jumps to the handler's invoke method, where the expression method.invoke(person, args) is evaluated. The trick is to remember that this line of code is equivalent to:
  object.equals(person)
This evaluates to false because:
  • The object is an instance of Proxy.
  • The person is an instance of IPerson.
  • Both instances are distinct objects.
  • The Proxy class inherits its equals(Object) method from Object.
  • The expression object == person evaluate to false.

It is unfortunate that the Proxy class does not take care of ensuring that the equals(Object) method just works as you would expect, but sadly this is not the case. If you want it to work, and you really do want it to work, your InvocationHandler must be smarter. But I'm saving that for another day.

Planet Eclipse

Jazz Community News