Wednesday, January 30, 2008

Bad style - Architecture Diagrams

Plain boxes linked with each other using lines; these kind of diagrams are fine to explain many things - until they are called "architecture". It is a wide-spread misconception, they are just plain diagrams, until they meet the requirements of an architecture diagram. But wait a minute. What are these requirements?
There are many definitions of software architecture. I don't want to go into the details of software architectures, many people did this before (read the POSA books or this, this and this). Instead, I'd like to discuss some of the most important properties of good architecture diagrams.
The first is an unambiguous language (in this case, graphical notations, but the architecture description can be textual as well) the architecture is expressed in. Completeness (remember: component, interface, connector, configuration) is also important. This language should be well-defined with respect to its syntax (the set of notations used) and semantics (the meaning of the notations and language constructs).
It can be very helpful if the graphical notations of the language are based on well-known graphical notations, such as the elements of UML component or class diagrams.
The diagrams must reflect the architectural decisions (which are based on requirements, of course) and they should be organized around architectural aspects and/or viewpoints. This is the most important thing.
The layout of diagrams should emphasize the architectural configuration. Position and connections of each element in every diagram should be in sync with the architecture. For example, a diagram should not show layers or partitions where they don't exist.
And that's enough for start. If a diagram is made with these things in mind, it is an architecture diagram.

Thursday, January 24, 2008

OSGi and DynamicImport-Package

Last week I refactored an old Spring-based application to be OSGi-based. First I created some bundles of it. It was a pleasure, I really like the Eclipse plug-in development tools, but it's not what I want to talk about.
One of the classes from the legacy app used dynamic class loading via Class.forName(). This class was a factory used to load other classes reside in many bundles. It is perfectly legal, but in order to load a class, the class loader of the bundle must be able to find it. This can be done nicely with "Import-Package: package.of.the.class.to.be.loaded". Of course, someone must export this package using Export-Package. But what happens when the factory class is referenced from the bundle exported that package? The answer is simple: circular dependency. You may say that it is a non-issue and can be solved easily using DynamicImport-Package, but lets think about that for a moment. What are the architectural consequences of such a decision?
Importing a package means you are about to create dependency to the bundle exporting that package. So even if your importing bundle works perfectly fine without the other (exporter) bundle, the exporter must also be deployed in order to satisfy the dependency.
Moreover, exporting means that you expose internals of the exporter bundle that are not part of the service's API provided by this bundle. By doing this, you may experience compatibility issues when you change the internals of this bundle in the future, even if the service API remains the same.
With the above in mind, I decided to refactor the affected bundles to eliminate circular dependency instead of just "work around" the problem using DynamicImport-Package.
To wrap it up: I suggest you to think about the architecture first and use DynamicImport-Package if you really need it.

Monday, January 14, 2008

OSGi and the infamous class loading problems

I just fought my fight with OSGi and JCL (Jakarta Commons Logging). I was porting an old Spring-based app to OSGi+Spring-DM, so I tried to use commons logging in my bundles. This ended up getting a nice exception:

org.apache.commons.logging.LogConfigurationException:
java.lang.NoClassDefFoundError (Caused by
java.lang.NoClassDefFoundError)
...

So I refactored all of my bundles to use the OSGi LogService instead of JCL. Re-deploy, start ... and no change. After some googling I found an interesting article which explained that JCL uses a custom class loading scheme which does not cause problems in standalone applications, but shows this weird behaviour under an OSGi environment. The article pointed to another logging framework (SLF4J) which provided a nice solution for the problem. A few lines from my config.ini:

jcl104-over-slf4j-1.4.3.jar@start,\
slf4j-simple-1.4.3.jar@start,\
slf4j-api-1.4.3.jar@start,\

And that's all. So please do not use JCL unless you want to bang your head against the wall.

(This madness drove me to an OSGi-related rule of thumb: if something looks suspicious around your bundles and you have no idea what's wrong, you may have a class loading issue.)