tag:blogger.com,1999:blog-68741490974780739292023-11-15T15:20:16.212+01:00fmeschbe's blogfmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-6874149097478073929.post-74987977342260355022012-11-06T09:25:00.000+01:002012-11-06T09:25:02.915+01:00OSGi DevCon 2013 coming soonOSGi DevCon 2013 once again is co-located with EclipseCon 2013 taking place in Boston, Massachusetts, between March 25 to 28. See the OSGi Alliance <a href="http://www.osgi.org/DevCon2013/HomePage" rel="nofollow" target="_blank">announcement</a> for full details.<br />
<br />
The call for papers is still open until November 19, so hurry up and <a href="http://www.eclipsecon.org/2013/propose-session" rel="nofollow" target="_blank">submit</a> a talk. For teasers an early bird selection has been taken: <a href="http://www.eclipsecon.org/2013/sessions/modularity-cloud-case-study" rel="nofollow" target="_blank">Modularity in the Cloud: a Case Study</a> by by Paul Bakker and Marcel Offermans from Luminis.
<br />
<br />
Hop to see you next March in Boston.fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-78532690358775317822011-04-18T19:18:00.008+02:002011-04-18T20:04:59.997+02:00Apache Sling 6 Released<div>Bringing Back the Fun</div><div><br /></div><div>Apache Sling brings back the fun to Java developers and makes the life of a web developer much easier. It combines current state of the art technologies and methods like OSGi, REST, scripting, and JCR.</div><div><br /></div><div>The main focus of Sling deals with the important task of bringing your content into the web and providing a platform to manage/update the content in a REST style.</div><div><br /></div><div>Sling is built as OSGi bundles and therefore benefits from all advantages of OSGi. On the development side a scripting layer (leveraging the Java Scripting API) allows to use any scripting language with Sling (of course you can use plain old Java, too). And on top of this, Sling helps in developing an application in a RESTful way.</div><br /><div>As the first web framework dedicated to JSR-283 Java Content Repositories, Sling makes it very simple to implement simple applications, while providing an enterprise-level framework for more complex applications. Underneath the covers Apache Jackrabbit is used for the repository implementation.</div><br /><div>Download the new release, Apache Sling 6, today and give it a try!</div><br /><div>Apache Sling currently comes in four flavors:</div><div><ul><li>A standalone Java application (a jar containing everything to get started with Sling)</li><li>A web application (just drop this into your favorite web container)</li><li>The full source package (interested in reading the source?)</li><li>Maven Artifacts (available from the Central Maven Repository)</li></ul></div><div>For more information, please visit the <a href="http://sling.apache.org/">Apache Sling web site</a> or go directly to <a href="http://sling.apache.org/site/downloads.cgi">the download site</a>.</div><br /><div>For those interested in numbers: Since the Apache Sling 5 announcement ...</div><div><ul><li>22 months have passed</li><li>7 committers have been added to Apache Sling</li><li>3 members have been added to the Apache Sling PMC</li><li>158 releases have been cut and voted on</li><li>~2800 commits have been sent to the SVN repository</li></ul></div><div>I would like to thank every user, contributor, committer and member of the PMC for their hard work and sometimes patience for making Apache Sling 6 a reality.</div>fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-90529534233421904082011-04-11T10:05:00.006+02:002011-04-11T10:43:09.609+02:00To embed or to inline ?At times you want (or need) to include third party libraries in your bundles. You basically have two options to do that:<br /><ul><li>Embed the complete library</li><li>Inline the required classes/packages (or everything)</li></ul><div>Until recently I was in the camp of embedding the complete libraries and setting the <span class="Apple-style-span" >Bundle-ClassPath</span> manifest header accordingly. The <i>Embed-Dependency</i> directive of the <a href="http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html">Apache Felix Maven Bundle Plugin</a> makes this extremely easy to do.</div><div><br /></div><div>Lately, though, this has been questioned by Karl Paul's <a href="http://code.google.com/p/pojosr/">pojosr</a> project. This project brings the OSGi Service Registry to regular applications. The nice thing here is, that it really is a stripped down OSGi Framework basically removing the modularity pillar. The drawback is that this causes the Bundle-ClassPath manifest header and embeddeded libraries to not be supported.</div><div><br /></div><div>Thus to run your regular bundle inside pojosr, you will have to inline all third party libraries instead of embedding them. The upside is that this really works. For example the Apache Felix Declarative Services implementation works flawlessly after inlining the KXml library.</div><div><br /></div><div>So, this sparked a discussion of whether embedding or inlining third party libraries is preferrable. And contrary to my former believe (embedding is preferable) it turns out that inlining is probably preferable for a number of reasons:</div><div><ul><li>You can just include those classes, that you really need. In fact recent builds of Peter Kriens' fantastic <a href="http://www.aqute.biz/Bnd/Bnd">BND</a> tool now supports an experimental Conditional-Package header which allows to inline packages conditionally: <i>Works as private package but will only include the packages when they are imported. When this header is used, bnd will recursively add packages that match the patterns until there are no more additions</i> (quoted from <a href="http://www.aqute.biz/Bnd/Format">http://www.aqute.biz/Bnd/Format</a>). This leads to smaller bundles.</li><li>The OSGi framework can more easily create the class loader for the bundle, because everything is just contained directly within the JAR file. For embedded libaries, these have to be unpacked, place on the filesystem and added to the class loader.</li><li>Performance will probably increase because everything is in a single JAR file and does not have to be searched in multiple JAR files</li><li>Memory Footprint will also be likely be reduced due to only a single JAR file being accessed.</li><li>Chances are that even the number of consumed filehandles will be reduced.</li></ul><div>There is a drawback, though: If you happen to include a signed third party library or a library which you are contractually or by license not allowed to modify, you must embed it completely.</div></div><div><br /></div><div>Overall, this discussion changed my mind bringing me to the inline-preference camp...</div><div><br /></div><div>So, you might expect to see a few of the Apache Felix and Apache Sling bundles I am working on to me modified to inline third party libraries instead of embedding them. In fact the Apache Felix Declarative Services and Web Console projects have already been modified to inline the third party libraries...</div>fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-81802136942504968872010-12-10T07:51:00.005+01:002010-12-10T08:07:51.430+01:00Class.forName ? Probably not ...After subscribing to the <a href="http://www.osgi.org/Planet/HomePage">OSGi Planet feed</a> I felt like starting to read some old blog posts and stumbled upon a series of posts by BJ Hargave around the issues of the <a href="http://wiki.eclipse.org/index.php/Context_Class_Loader_Enhancements">Eclipse ContextFinder</a> caused by the <code>Class.forName</code> methods.<br /><br />For the full story please go and read <a href="http://blog.bjhargrave.com/2007/09/classforname-caches-defined-class-in.html">Class.forName caches defined class in the initiating class loader</a> (and folow the links !).<br /><br />So, these posts caused me to try and look how we behave in <a href="http://sling.apache.org">Apache Sling</a> ... and of course hoped we would be clean.<br /><br />Well, hmm, turns out we are not ... I found nine classes using <code>Class.forName</code>. <br /><br />So we probably have to clean this up. Maybe or maybe not, these uses may be the cause for some strange failures we had over time. I cannot really tell. But I cannot exclude this possibility either.<br /><br />BTW, this is what I did to find the classes:<br /><blockquote><code>$ find . -name "*.java" -exec fgrep -l Class.forName {} \;</code></blockquote>fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com2tag:blogger.com,1999:blog-6874149097478073929.post-52161603295950736842009-10-15T13:50:00.011+02:002012-10-11T10:57:02.299+02:00On Version NumbersI have been thinking about using version numbers lately while working on some API extension of the Sling Engine bundle. So here is what I think versions are all about and that we all should be very careful when changing code and assigning versions to it.<br />
<br />
On a high level versions have various aspects:<br />
<dl>
<dt>Syntax</dt>
<dd>There is no global agreement on the correct syntax of versions. I tend to like the OSGi syntax specification: The version has four parts separated by dots. The first three parts are numbers, called the major, minor and micro version. The fourth part is a plain (reduced character set) string which may be used to describe a particular version. Version numbers are compared as you would expect, except that the fourth part is employs case-sensitive string comparison comparing the actual Unicode codepoints of the characters.</dd>
<dt>Semantic</dt>
<dd>The semantics of a version define what it means to increment each place of a version. In the world of software development there is even less agreement on the semantics of version numbers than there is agreement on the syntax. The OSGi specification just defines suggested semantics.</dd>
<dt>Expectations</dt>
<dd>When seeing product version numbers people tend to have expectations towards the products. For example when Firefox went from 2.x to 3.0 we expected a major change. Likewise when Day upgraded the version number to 5 for the newest version of Communiqué the expectation is correct, that it is a major new version of the product. In fact we completely rewrote Communiqué for the 5.0 release.</dd>
<dt>Version Items</dt>
<dd>When it comes to apply version numbers to things there are quite a number of things in a single product, which may be numbered. Take for example Day Communiqué 5. There is a product - the thing you take out of the box and install on your server. Then there are OSGi bundles. Finally there are Java packages shared between the bundles and used by the application scripts.</dd></dl>
So here are my definitions of the version number aspects layed out above.<br />
<br />
<h3>
<b>Syntax</b></h3>
IMHO the Syntax for version numbers as defined in the OSGi Core specification (Section 3.2.4, Version) is good enough and clear for most uses. The nice thing about this specification is that in Section 3.2.5, Version Ranges, a syntax is defined to define ranges of versions. Such ranges are of great use when depending on other items. Most importantly of course this would be list of imported Java packages.<br />
<br />
<h3>
Semantics</h3>
As for the semantics the main problem comes from the fact, that not all versioned items understand version numbers in the same way. For example on a product level, c.f. Day Communiqué, the version number of a release is generally defined by marketing and/or product management.<br />
<br />
I will not dive into how product numbers are to be defined. This is outside of my working knowledge and beyond may abilities ;-)<br />
<br />
On the OSGi bundle level on the other hand and even more so on the Java package level (for OSGi package exports), the version number is more a call of the developer. Version numbers on this level are intended to convey to other developers something about the evolution of the bundle and/or package.<br />
<br />
Let's start with exported Java packages. I tend to attribute the following semantics to the parts of a a version number:<br />
<ul>
<li>Increasing the major version number means the API has been modified in an incompatible way. Mostly this means public classes, interfaces, methods, fields have been removed or renamed. As a consequence code using and implementing the API will break and has to be modified.</li>
<li>Increasing the minor version number means the API has just been enhanced in a way that is compatible for use. Increasing the minor version number, though, means that code implementing the API might have to be modified to comply with the added API like the definition of new methods.</li>
<li>Increasing the micro version number means that there have been some bug fixes. Generally, a pure API consisting of just interfaces has little chance for bugs which do not ammount to minor or even major version number increase. If the exported packages of a bundle happen to contain concrete or abstract classes with implementation code, bugs cannot be excluded. As such it is conceivable that a the micro version number of an exported package might be increased.</li>
<li>As for the qualifier part, as the fourth part of a version number is called by the OSGi specification, this meaning of this part is completely free. On a package export level, I would go as far as to say, it should not generally be used. The qualifier part may be interesting on an OSGi bundle level to create inter-release builds.</li>
</ul>
<br />
<br />
<h3>
<b>Expectations</b></h3>
Peoples expections as it comes to version numbers is not ease to convey. Most people expect different things. But I think one thing is common to all: If there is a version number increase something must have changed.<br />
<br />
So, I think to use developers it is important to understand, that we only increase the version number of an item if there is a change -- not sure whether a fixed spelling error in some Java comment is change enough. Again, your mileage may vary if you happen to be product manager for a product to be sold ....<br />
<br />
<h3>
<b>Recommendations</b></h3>
Based on how I understand the version number parts in terms of exported packages, here are my recommendations for package imports and bundle versions.<br />
<ul>
<li>If you implement the exported API of another bundle, import the API package using a version range of the form [x.y,x.y+1). This means accept any increment in the micro and qualifier parts. But as soon as the minor version number changes, consider this an incompatibility.</li>
<li>If you use an exported API, import the API package using a version range of the form [x.y,x+1). This means accept any version starting with a minimum number upto the next breaking API chnage identified by a new major version number.</li>
<li>Don't increase the version number of an API package if nothing in that package has changed at all.</li>
<li>Bundles should be versions following versioning of exported packages. So if at least one of the exported packages has a major version number increase, the bundle's version should also have a major version number increase. Likewise for the minor number. The use of qualifiers is optional and sometimes helpful.</li>
<li>Apart from being driven by versioning of exported packages, bundle versions may also be increased depending on the extent of changes in the bundle. For example in the case of a pure implementation bundle, greatly increasing the functionality might give rise to a major version number increase of the bundle.</li>
<li>If you are using Maven to build your projects, always depend on the lowest version of a dependent module which has the API functionality you need.</li>
</ul>
<br />
<br />
<h3>
<b>Link</b></h3>
The Eclipse site contains a very interesting and IMHO very reality proven text about versioning of products, bundles and packages: <a href="http://wiki.eclipse.org/index.php/Version_Numbering">Version Numbering</a><br />
<h3>
<b>Update 2012/10/11</b></h3>
The OSGi Alliance released an excellent white paper on <a href="http://www.osgi.org/wiki/uploads/Links/SemanticVersioning.pdf" target="_blank">Semantic Versioning</a> which pretty much aligns with what I was talking about above.<b> </b> fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-78789680945470263402009-04-17T09:06:00.004+02:002009-04-17T09:24:03.638+02:00Ready to serve requests ...In the <a href="http://incubator.apache.org/sling">Apache Sling</a> project we have an <a href="https://issues.apache.org/jira/browse/SLING-490">interesting problem</a>: Knowing when the application has finished its startup.<br /><br />Coming from a background of a traditional application, you know when the system has finished its startup. For example, a servlet container knows it has finished the startup, when all web applications have been started.<br /><br />In Apache Sling, the situation is a bit different: Apache Sling is an extensible system, where extensions may simply be added by adding more bundles. "Easy", you say, "just wait for all bundles to have been started and you know when the application is ready". True, but there is a catch.<br /><br />To extend Apache Sling, you register services with the OSGi registry. "Still easy", you might say. Right, if the services are all started by bundle activators, we still can depend on having all bundles started for the system to be ready.<br /><br />Again, this is only part of the story: Some services depend on other services. So the dependent services may only be started when the dependencies get resolved. This is where the trouble starts.<br /><br />To help solve the dependency issues in a simple way, we employ OSGi Declarative Services. Great things to define components and services and have the dependency requirements being enforced and have dependency injection and configuration support and ... much more.<br /><br />"What does it cost?", you say. Well, we buy this functionality with a lot of asynchronicity: When all bundles have been started, not all components may have been activated and not all services may have been registered.<br /><br />Now, when is the application ready ? I cannot easily tell.<br /><br />One approach could be to have a special service to watch out for a configurable list of services to be available. When all services are available and after the framework has started, the service signals <i>Application Ready</i>. As soon as one of the services goes away, the service might signal <i>Application Not Ready</i>.<br /><br />The real question raising now is: What services are required for the application to be considered ready ? Can we come up with such a list ? How to we manage this list in light of more services to come, which might be considered vital ?<br /><br />Any input would be appreciated ;-)fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com2tag:blogger.com,1999:blog-6874149097478073929.post-14861482805439054632009-04-17T08:40:00.008+02:002009-04-17T09:04:15.773+02:00Dependency Injection in OSGiThe OSGi framework and its compendium services provide a whole lot of fun to build applications. Defining bundles is a cool stuff to cut the big job into pieces and enjoy the coolness of separation of concerns just like the old Romans said: Divide et Impera !<br /><br />One interesting compendium specification is the Declarative Services Specification. This specification tries and IMHO succeeds very well to bring some of the cool stuff of Spring, namely Dependency Injection, into the OSGi world. Just like the application descriptors in Spring you have component descriptors in Declarative Services.<br /><br />Using a component descriptor, you define the following properties of a component:<br /><br /><ul><br /><li>The name of the component and whether it is activated immediately or not</li><br /><li>Whether the component is a service and the service interfaces to register the component with</li><br /><li>Which other services are used by the component. These services may be injected (bound in OSGi speak) or may be looked up. There is also the notion of mandatory and optional services which provides the functionality to delay the component action until the mandatory service becomes available.</li><br /><li>Configuration properties. Some properties may be injected by the descriptor itself. But at the same time, configuration properties may also be overwritten by configuration from the Configuration Admin Service. Thus the configuration of components may even be very dynamic.</li><br /></ul><br /><br />The good news for the XML-haters like me: Over in the Apache Felix project we have <a href="http://felix.apache.org/site/apache-felix-maven-scr-plugin.html">Maven 2 plugin</a> which takes annotations (JavaDoc or Java 5 Annotations) from your Component classes and builds the descriptors on your behalf.<br /><br />So the next time, you are looking for dependency injection, you might want to consider OSGi and Declarative Services ;-)<br /><br />Just for completeness, here is a list of other frameworks providing some sort of dependency injection:<br /><br /><ul><br /><li><a href="http://felix.apache.org/site/apache-felix-ipojo.html">Apache Felix iPOJO</a></li><br /><li><a href="http://felix.apache.org/site/apache-felix-dependency-manager.html">Apache Felix Dependency Manager</a></li><br /><li><a href="http://www.springsource.org/osgi">Spring Dynamic Modules</a></li><br /><li><a href="http://www.kevindog.com/sat/help/topic/org.eclipse.soda.sat.plugin.doc/books/book.html">Eclipse Service Activator Toolkit</a></li><br /><li><a href="http://code.google.com/p/peaberry/">Peaberry</a></li><br /></ul><br /><br />In the end all work more or less the same, in that the provide some abstraction layer on top of the basic OSGi framework functionality: the Service Registry. This is really, the greatest things of all and IMHO shows the cleverness of the OSGi Framework specification: With just three basic layers (modularity, lifecycle and the service registry), you get the whole world in your hand to build flexible, modular and extensible applications.fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-86093231779710589552008-10-08T09:30:00.003+02:002008-10-08T09:48:04.717+02:00OSGi Framework Extension as a Maven ProjectIn a previous <a href="http://blog.meschberger.ch/2008/10/osgi-bundles-require-classes-from.html">post</a> I explained how to extend an OSGi framework such that more classes are visible inside the framework from the outside world. This posting provided a very simple example to generate Framework Extension Bundle using a single file and calling the JAR tool from the command line. Here I will expand on this example by creating a Maven 2 project, which may be used in environments where Maven 2 is used for project builds.<br /><br /><br />As a first step, we need a Maven 2 project descriptor. To create this beast, we have to decide, how we build the project. I generally use the <a href="http://felix.apache.org/">Apache Felix</a> <a href="http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html">Maven Bundle Plugin</a> to build my projects as OSGi bundles. This great plugin comes with support for Maven 2 packaging but also provides goals to call if the packaging functionality should not be used.<br /><br />Before talking too much, let me just present a project descriptor, which I know works. After that I will explain why I did it, like I did it.<br /><br /><pre><br /><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><br /><modelVersion>4.0.0</modelVersion><br /><groupId>ch.meschberger.sample</groupId><br /><artifactId>ch.meschberger.sample.sysext</artifactId><br /><version>0.0.1-SNAPSHOT</version><br /><packaging>jar</packaging><br /><br /><name>System Bundle Extension Sample</name><br /><description><br /> This sample bundle extends the System Bundle export<br /> list with the com.sun.image.codec.jpeg package such<br /> that OSGi bundles may refer to Sun's JPEG implementation<br /> without the OSGi framework itself to provide it in a<br /> non-portable way.<br /></description><br /><br /><build><br /> <plugins><br /> <plugin><br /> <artifactId>maven-jar-plugin</artifactId><br /> <configuration><br /> <forceCreation>true<br /> <archive><br /> <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile><br /> <manifestEntries><br /> <Export-Package>com.sun.image.codec.jpeg</Export-Package><br /> </manifestEntries><br /> </archive><br /> </configuration><br /> </plugin><br /> <plugin><br /> <groupId>org.apache.felix</groupId><br /> <artifactId>maven-bundle-plugin</artifactId><br /> <version>1.4.3</version><br /> <executions><br /> <execution><br /> <id>bundle-manifest</id><br /> <phase>process-classes</phase><br /> <goals><br /> <goal>manifest</goal><br /> </goals><br /> </execution><br /> </executions><br /> <configuration><br /> <instructions><br /> <Bundle-Category>sample</Bundle-Category><br /> <Fragment-Host>system.bundle; extension:=framework</Fragment-Host><br /> </instructions><br /> </configuration><br /> </plugin><br /> </plugins><br /></build><br /></project><br /></pre><br /><br />First of all, I use plain old <span style="font-style: italic;">jar</span> packaging. This allows me to have more control over the manifest generation. The problem is, that the Bundle plugin removes any packages from the <span style="font-style: italic;">Export-Package</span> header of the generated manifest which happen to not be present in the final JAR file. This is very good in all cases except in our case, which may of course be considered a special case.<br /><br />So we use jar packaging. Still I like the wonderful setup of the Bundle plugin when it comes to setting the required OSGi manifest headers. Fortunately, the Bundle plugin allows me to generate a manifest file as if the packaging would be <span style="font-style: italic;">bundle</span>. This is the <span style="font-style: italic;">manifest</span> goal.<br /><br />Consequently, in the sample above, packaing is set to <span style="font-style: italic;">jar</span> and the Bundle plugin is configured to generate a manifest file with the standard headers plus the <span style="font-style: italic;">Fragment-Host</span> header required to mark the bundle as Framework Extension Bundle. For the Jar plugin to include the generated manifest we refer to it with the <span style="font-style: italic;">manifestFile</span> configuration element, which requires us to add the explicit Jar plugin configuration not normally needed.<br /><br />Now, we have the Bundle plugin generate the standard headers, we have the Jar plugin use that manifest but still we have two issues: First the Bundle plugin does not have the <span style="font-style: italic;">Export-Package</span> header definition, which would be useless because it would be removed anyway. And second, the Jar plugin would complain, because it has nothing to package.<br /><br />The first issue is fixed by adding a <span style="font-style: italic;">manifestEntries</span> element to the Jar plugin configuration, which lists the missing <span style="font-style: italic;">Export-Package</span> header.<br /><br />The second issue is just as easy to solve as the first: We just force the creation of the JAR file by setting the <span style="font-style: italic;">forceCreation</span> parameter.<br /><br />Unfortunately the Bundle plugin does not create the destination folder into which the generated manifest file is placed. To have this folder created, just create an empty <span style="font-style: italic;">src/main/resources</span> folder. This causes the destination to be created.<br /><br />That's it. We now just have to use Maven to build that project and we are done and can use it.fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com3tag:blogger.com,1999:blog-6874149097478073929.post-58371331940991347522008-10-08T09:10:00.000+02:002008-10-08T09:11:12.289+02:00OSGi Bundles require Classes from the EnvironmentImagine your great application running inside an <a href="http://www.osgi.org/">OSGi framework</a> such as <a href="http://felix.apache.org/">Apache Felix</a> or <a href="http://www.eclipse.org/equinox">Eclipse Equinox</a> and requiring a class, which you know is provided by the Java Platform but not provided inside the framework.<br /><br />For example, you provide functionality for the general user on the Internet to submit comments or register themselves but you want to protect this functionality from robots. To do this, you include a Captcha and decided to use the <a href="http://simplecaptcha.sourceforge.net/">simple java captcha library</a> from SourceForge. This library requires classes from the <code>com.sun.image.codec.jpeg</code> package. This package is generally not made visible inside the framework.<br /><br />So, what can you do ? Of course you could configure your OSGi framework to just make the package visible by configuring either the <code>org.osgi.framework.system.packages</code> or the <code>org.osgi.framework.bootdelegation</code> property accordingly. But what if you can't do that ?<br /><br />Here come the so-called Extension Bundles. Extension Bundles are actually Fragment Bundles, which attach to the System Bundle and extend the framework either by providing more exports from the System Bundle or by even appending to the class loader which loaded the OSGi framework.<br /><br /><br /><span style="font-weight: bold;">How can an OSGi Framework be extended ?</span><br /><br />A framework can be extended in two ways: Either by extending the list of packages available in the framework itself by ammending the System Bundle export list or by adding classes to the framework boot class loader.<br /><br />To extend the framework the bundle must have the Fragment-Host manifest header set to either the actual bundle symbolic name of the system bundle as defined by the framework vendor. Alternatively the alias of the system bundle name, which is <code>system.bundle</code> may be used. I prefer the latter case because it would not create vendor lock-in on the Extension Bundle.<br /><br />The type of extension is indicated by the <span style="font-style: italic;">extension</span> directive of the <ode>Fragment-Host manifest header. The directive may take either of the following values:<br /><br /></ode><ul><li><code>framework</code> -- A framework extension ammends the System Bundle export list</li><li><code>bootclasspath</code> -- The Extension Bundle jar file is added to the class path of the class loader loading the OSGi framework. As such, the classes from the Extension Bundle jar file are actually loaded <span style="font-style: italic;">outside</span> of the OSGi framework.<br /></li></ul><br /><br /><br /><span style="font-weight: bold;">Example 1: Provide the <code>com.sun.image.codec.jpeg</code> Package</span><br /><br />To continue our initial example, lets see how the <code>com.sun.image.codec.jpeg</code> package can actually be made visible to our Captcha bundle. To do this, we just need a manifest file which we package into a standard JAR file using the <code>jar</code> tool.<br /><br />Frist create a file -- say <code>manifest.mf</code> with the following contents:<br /><br /><pre><br />Bundle-ManifestVersion: 2<br />Bundle-SymbolicName: ch.meschberger.sample.extension<br />Bundle-Version: 0.0.1<br />Fragment-Host: system.bundle; extension:=framework<br />Bundle-Name: Sample Framework Extension<br />Bundle-Description: Sample Bundle exporting Sun's JPEG classes<br />Export-Package: com.sun.image.code.jpeg<br /></pre><br /><br />Now, create the bundle JAR file:<br /><br /><pre><br />$ jar -cfm ch.meschberger.sample.extension-0.0.1.jar manifest.mf<br /></pre><br /><br />That's it. After installing this bundle in your framework you can use the Sun JPEG classes as usual.<br /><br /><br /><span style="font-weight: bold;">Restrictions of Framework Extension Bundles</span><br /><br /><br />There are a few restrictions when using Framework Extension Bundles. First of all refreshing an Extension Bundle must cause the OSGi framework to stop and be restarted. An Extension Bundle enters the INSTALLED state but may enter the RESOLVED state only at the discretion of the OSGi framework. An Extension Bundle will never be in the STARTED state, though.<br /><br />Further restrctions exist for the Bundle Manifest headers. That is, the following headers are not allowed to be used in an Extension Bundle:<br /><ul><li>Import-Package</li><li>Require-Bundle</li><li>Bundle-NativeCode</li><li>DynamicImport-Package</li><li>Bundle-Activator</li></ul>This is not generally a restriction per-se, because it is very unlikely that any of these headers is actually required by an Extension Bundle. Nevertheless, you must take care to not set any of these headers.<br /><br /><br /><span style="font-weight: bold;">More Information</span><br /><br />More information on the Extension Bundles may be found in section 3.15, Extension Bundles, of the OSGi Service Platform Core Specification which is available for download from the <a href="http://www.osgi.org/Specifications/HomePage">specification page</a> of the OSGi Alliance.fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com0tag:blogger.com,1999:blog-6874149097478073929.post-48833210994890569572008-10-08T08:32:00.004+02:002010-04-12T11:55:29.363+02:00LinkedHashMap's hidden (?) featuresRecently I discovered two very nice features of the <tt>java.util.LinkedHashMap</tt>: <tt>accessOrder</tt> and <tt>removeEldestEntry(Entry)</tt>. These features combined let you implement simple LRU caches in under two minutes.<br /><br /><b><tt>accessOrder</tt></b><br /><br />The <tt>accessOrder</tt> flag is set when creating the <tt>LinkedHashMap</tt> instance using the <tt>LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)</tt> constructor. This boolean flag specifies how the entries in the map are ordered:<br /><br /><dl><br /><dt><tt>accessOrder=true</tt></dt><br /><dd>The elements are ordered according to their access: When iterating over the map the most recently accessed entry is returned first and the least recently accessed element is returned last. Only the <tt>get</tt>, <tt>put</tt>, and <tt>putAll</tt> methods influence this ordering.</dd><br /><dt><tt>accessOrder=false</tt></dt><br /><dd>The elements are ordered according to their insertion. This is the default if any of the other <tt>LinkedHashMap</tt> constructors is used. In this ordering read access to the map has no influence on element ordering.</dd><br /></dl><br /><br /><b><tt>removeEdlestEntry(Entry)</tt></b><br /><br />The second feature of interest is the <tt>removeEldestEntry(Entry)</tt> method. This method is called with the eldest entry whenever an element is added to the map. <i>Eldest</i> means the element which is returned last when iterating over the map. So the notion of <i>eldest</i> is influenced by <tt>accessOrder</tt> set on the map. The <tt>removeEldestElement</tt> in its default implementation just returns <tt>false</tt> to indicate, that nothing should happen. An extension of the <tt>LinkedHashMap</tt> may overwrite the default implementation to do whatever would be required:<br /><br /><ul><br /><li>If the implementation decides to remove the eldest element for any one reason, say a size limitation, it just returns <tt>true</tt> and the eldest element is removed from the map</li><br /><li>The implementation may also decide to modify the map itself in some way or the other. But in this case, the implementation should return <tt>false</tt>, otherwise the eldest element will still be removed.</li><br /></ul><br /><br /><br /><b>A simple LRU Cache</b><br /><br />Taking the two features together, a very simple LRU Cache may be implemented in just a few lines of code:<br /><br /><pre><br />public class LRUCache<K, V> extends LinkedHashMap<K, V> {<br />private final int limit;<br />public LRUCache(int limit) {<br /> super(16, 0.75f, true);<br /> this.limit = limit;<br />}<br />@Override<br />protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {<br /> return size() > limit;<br />}<br />}<br /></pre><br /><br />The mechanism is very easy: The <tt>LRUCache(int)</tt> constructor initializes the map with the default initial size and load factor and sets the map into <tt>accessOrder</tt> mode. The <tt>removeEldestEntry</tt> just checks the current map size (after the addition of a new entry) against the <tt>limit</tt> and returns <tt>true</tt> if the limit has been reached.<br /><br />A real world implementation would of course have to check and handle the <tt>limit</tt> value on the constructor.<br /><br /><br />To see a <tt>LinkedHashMap</tt> based LRU Cache in action, have a look at the <a href="http://svn.apache.org/viewvc/incubator/sling/trunk/bundles/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceCache.java?view=markup"><tt>BundleResourceCache.BundleResourceMap</tt></a>. This implements a simple entry cache to speed access to OSGi Bundle entries. To not waste memory, the size of the cache is limited.fmeschbehttp://www.blogger.com/profile/14510099790398523034noreply@blogger.com6