Example OSGi Web Application

In some of my OSGi talks I use the “Guessing Game” as the next great web application to conquer the world. It’s a web app that generates a random number and let’s you guess it, telling you whether you made it, are too high or too low.

You can find the latest sample code on github.

Some slides from the last OSGi Community event featuring this app:

Http Whiteboard – Simply Simple – Part I

Developing web components with OSGi can be very simple if you’re using the OSGi Http Whiteboard Specification (see OSGi Compendium Chapter 140). For example the Apache Felix Http Implementation supports this standard.

In this part of the tutorial we start pretty simple and just look at how to develop a servlet and register it as an active web component. In the next parts we’ll cover more details.

For the example we use Declarative Services (DS) to develop our components. This is the easiest and most elegant way of developing OSGi services and is a standard for OSGi component development (see OSGi Compendium Chapter 112). For a tutorial for Declarative Services see OSGi Components Tutorial.

Registering A Servlet with the Http Whiteboard

Let’s have a look at the typical Hello World Example. The below code registers a servlet which simply prints out Hello World if invoked.

@Component(service = Servlet.class, 
           scope=ServiceScope.PROTOTYPE,
           property= "osgi.http.whiteboard.servlet.pattern=/hello")
public class HelloWorldServlet extends javax.servlet.http.HttpServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
        resp.getWriter().println("Hello World");
    }
}

With the @Component annotation the HelloWorldServlet is registered as a service of type Servlet with a prototype scope. Using the prototype scope for servlets is recommended and we’ll see in another part why. The more important property is osgi.http.whiteboard.servlet.pattern which defines the path under which the servlet is available, /hello in this case. Once deployed into an OSGi application which has support for the OSGi Http Whiteboard specification, this servlet is reachable using /hello from your browser.

And that’s all you have to do. So getting a servlet up and running comes down to using the @Component annotations and specifying the path. Everything else is taken care of and you can focus on implementing your business logic. Of course all the nice features of Declarative Services can be used within your servlet, like the @Reference annotation to use other services.

OSGi Components – Simply Simple – Part III

In the previous two parts (Part I and Part II) you learned how to use Declarative Services to develop your own components and services for OSGi. The topics included:

  • Creating components
  • Component lifecycle
  • Component configuration
  • Using services through references
  • Providing services

In this part we’ll cover another interesting topic:

Metatype Generation

The metatype specification (OSGi Compendium Chapter 105) provides a way to describe the configuration for a component. In general an OSGi configuration is just a dictionary with arbitrary key-value pairs. By defining a metatype description for the configuration, the developer of a component can define which properties together with their type the component expects. Such a metatype information can be used at runtime to generate forms to edit/create the configuration of a component. For example the Apache Felix Web Console does exactly that.

Now if you look at Part II of this series, if a component is configurable it contains already a component annotation for its properties:

public @interface MyComponentConfig {
     
    String welcome_message() default "Hello World!";
 
    int welcome_count() default 3;
 
    boolean output_goodbye() default true;
}

The above annotation already defines all possible properties together with their default values. Therefore the only thing you have to do is provide some human readable information like a label and a description for both, the configuration as a whole and each property. This can be done with some annotations from the metatype specification:

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@ObjectClassDefinition(name = "Hello World Configuration",
		description = "The configuration for the hello world component.")
public @interface MyComponentConfig {
     
    @AttributeDefinition(name="Welcome Message", description="This message is displayed on startup of the component.")
    String welcome_message() default "Hello World!";
 
    @AttributeDefinition(name="Welcome Message Count", description="This is the number of times, the welcome message will be displayed. " +
                              "If less than one, no message will be displayed.")
    int welcome_count() default 3;
 
    @AttributeDefinition(name="Output Goodbye", description="Set this if the component should output a goodbye message.")
    boolean output_goodbye() default true;
}

The @ObjectClassDefinition annotation is used on the whole configuration annotation and for each attribute, the @AttributeDefinition annotation is used. With these annotations a metatype description for the MyComponentConfig class will be generated. However, we want to bind this configuration to our component which is a different class. Therefore you have to specify the @Designate annotation on your component class:

import org.osgi.service.metatype.annotations.Designate;

@Component
@Designate( ocd = MyComponentConfig.class )
public class MyFirstComponent {
 
    @Activate
    protected void activate( MyComponentConfig config ) {
    ...
}

And this will generate the metatype information for your component. It’s really easy to do such and it helps the user of your component to easily figure out how your component can be configured.

OSGi Components – Simply Simple – Part II

In part I I motivated that developing OSGi components is plain and simple by Declarative Services and the provided annotations. We learned how to create a component, add lifecycle methods and reference services. If you haven’t read the first part yet, make sure to go there first.

Usually a component takes some configuration. So let’s have a look at this next.

Component Configurations

If you want to make your component configurable, the best way of doing this is to leverage the OSGi Configuration Admin (another spec from the OSGi compendium with again a great implementation at Apache Felix). Configuration Admin is a service persisting configurations – these configurations are dictionaries where the key is a string and the value can be one of the simple Java types or an array or collection of such a type. This is usually sufficient for most components.

Configuration Admin nicely abstracts managing the configuration from your component. As a component developer you don’t need to know where the actual configuration is stored and how it ends up there. Without a component container, you would ask the configuration admin for “your” configuration (though there is some injection support through the ManagedService interface) – but fortunately with DS the container takes care of this and provides your component with the configuration. The component might get the configuration as a parameter for the activate method.

As mentioned Configuration Admin stores configurations as dictionaries. Whereas the names are of type String, the value can be any type. While your component might expect an integer, e.g. for a port, the actual value stored might be of type String holding an integer value. Therefore it is good style to not assume a specific type but try to convert whatever you get into the expected type. To avoid putting the burden of doing this on the component developer and to support type safe configurations, the configuration for a component can be described in Java. While the following might look a little bit out of the ordinary, stick with me, you’ll get used to it pretty soon and simply love it.

The way to describe a configuration is by defining an annotation describing all configuration properties. Let’s assume our component has three configuration properties, then the following annotation would do:

public @interface MyComponentConfig {
    
    String welcome_message() default "Hello World!";

    int welcome_count() default 3;

    boolean output_goodbye() default true;
}

Defining an annotation instead of a simple interface has the advantage that we can directly specify default values for each property. If no value for a property is stored in configuration admin, the default value is used. Let’s see how to use this:

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;

@Component
public class MyFirstComponent {

    @Activate
    protected void activate( MyComponentConfig config ) {
        for(int i = 0; i < config.welcome_count(); i++ ) {
            System.out.println(config.welcome_message());
        }
    }
}

When the above component is activated, SCR tries to get a configuration from the configuration admin and converts it into the used annotation type. Therefore the passed in object returns the value in the correct type for each property. As mentioned if there is no value, the default is returned. This makes handling of configurations very simple and avoids all the usual boilerplate code. The OSGi specification for Declarative Services explains in detail how the type conversion is done and what happens if a value can’t be converted. It also defines the conversion rule from the name of a property in the annotation to a property in configuration admin. In the example above we see the underscore in the names, this is acutally converted to a dot in the property name.

Taking configurations is as easy as this: define your set of configuration properties as an annotation and pass it as an argument to the activate method. Of course, if you don’t need configuration, leave out these steps and use the zero argument activate method signature – or if you don’t need the activate method at all, leave it out completely.

With this knowledge we can already develop configurable components capable of using other services. But how do you provide a service for others to be used?

Services

Offering a service usually consists of two steps. First you define the service API and second you implement this API. Of course, in some cases the API might already exist as someone else defined the interface. If you define your own interface, put it into a public package and export this package – however, as already noted above for the component, a service implementation should never be public but in a private package. It depends on your use case, if you put the interface and the implementation in the same bundle or create an API bundle and an implementation bundle. If you’re implementing an existing interface, this usually is already in another bundle and you can just import it. And if you create public API, don’t forget to use proper versioning for these packages. Have a look at the semantic versioning whitepaper!

Offering a service is implementing the corresponding interface and registering the component in the OSGi service registry as the service. With the annotations you can just use the @Component annotation. Assume there is an interface EventHandler and your component should be registered as a service for this interface:

import org.osgi.service.component.annotations.Component;

@Component
public class MyFirstService implements EventHandler {

   ....// implement the EventHandler interface

}

Without further specifying anything at the @Component annotation, a component is registered as a  service for all interfaces it directly implements. In this case this is the EventHandler. While this is very convenient, it comes with the problem, that as soon as your component is implementing an interface directly, it gets registered as this service. In some cases this is not what you want. Therefore I suggest to:

  1. Always explicitely list the service interfaces the component implements:
    @Component(service = EventHandler.class}
  2. As a default always set the service attribute of the component annotations to the empty array. This prevents the automatic registration:
    @Component(service = {})

If you follow these simple rules, you can see directly by looking at the @Component annotation which services this component implements and you avoid accidental service registrations, e.g. when refactoring your implementation.

Lifecycle of a Service

A component which does not provide a service is active for as long as it is satisfied (all referenced services are available and some other conditions we get to later). In contrast, services are instantiated lazy or on demand by DS. This means, as long as no one is using your service, your service is never created nor activated! In most cases this is fine. But there is a catch with this approach one should be aware of: if someone else is starting to use your service, it gets created and activated. As soon as your service is not used anymore, it gets deactivated and destroyed. (The OSGi spec does not mandate this behaviour, it is also possible that your service is kept around for some time until it is disposed. But the current Apache Felix implementation works exactly as described above).

This behaviour might create a performance bottleneck if your service is created/destroyed (very often) for example on each request and/or if your service is doing some computation in the activate method.

To avoid this, you can either think about holding the service by someone else and therefore keep a reference to it around (which in general sounds hacky though there are valid use cases). Or you can use the immediate flag on the @Component:

@Component(service=EventHandler.class, immediate=true)

With immediate set to true, the component is activated as soon as possible and kept as long as possible. Obviously, this increases things like startup time, memory consumption etc. So it should really be used with care and maybe only after problems are encountered in this area. So far, apart from event handlers, we never encountered a real need for using immediate!
If you are implementing an OSGi event handler, service org.osgi.service.event.EventHandler, you should make your service immediate as otherwise it is potentially created/destroyed with each event for this handler! However, even this is up to the implementation of the event admin, the latest Apache Felix event admin implementation and the Equinox event admin implementation do not create/destroy the instance on each request, they rather create it once the first event for this component arrives and keep a reference to it from that point on. But as this is implementation specific, the above advice stands. And again, only use immediate if really required.

And with this the simple introduction to Declarative Services ends: you now know:

  • how to create components
  • how to configure components
  • how to reference services
  • how to provide services

Of course with most of this we only touched the simple case, which is really sufficient for most use cases. I’ll continue this series with more advanced stuff in the future.

OSGi Components – Simply Simple – Part I

There is a lot of prejudice and misunderstanding when it comes to OSGi. As with every technology there is a learning curve and some things might be different than you are used to. But change isn’t necessarily a bad thing.

Component-oriented development is a very common and powerful software engineering style where you assembly your application out of components. A component might offer a service, e.g. a scheduler service. Other components can use this scheduler service.

Or a little bit more formal: a component is a piece of software managed by a (component) container. In Java this means this is an instance, created and managed by a container. Therefore it’s not the task of the developer to create or configure these instances. This is the task of the container. If the component uses other services, it’s also the task of the container to pass these services to the component. Therefore a service is a component which provides one or more services. In Java this means a service implements one or more interfaces where an interface represents the service description.

OSGi Components with Declarative Services

I will show that developing components with OSGi is really simple and straightforward with no additional cruft – and I think it can’t really get much easier than this. We’ll be using the Declarative Services specification(see OSGi Compendium Chapter 112) in it’s latest version (R6). With the use of the annotations also defined in this specification, components are usually POJOs with all its benefits.

I will not go into the usual tooling discussion – there are different tools out there for your favorite development environment for processing these annotations, like Ant, Maven, Gradle. In contrast to other solutions, all the annotations are build time annotations. They are processed by some tooling and create additional files which are put in the final jar (bundle). I don’t explain everything in every detail and leave out things here and there – it is advisable to read the mentioned specs in addition!

Please note, that using Declarative Services (DS) is one way of developing components and services for OSGi, there are other approaches like Blueprint, Apache Felix iPojo, Apache Felix Dependency Manager etc. Each one of these solutions (including DS) has pros in some areas while it has cons in others. I think, DS is a simple and straightforward way of developing components. It’s easy to learn, easy to manage and maintain and provides all required features. However, if you plan to use something different than DS, the real good news is: you can mix and match all these approaches – they’re all based on the OSGi service registry and work well together!

With Declarative Services we have a nice component container managing our components and providing them with configurations and required services. As we’re talking about OSGi here, we’re talking about bundles, so the classes for your component or service go into a bundle. Declarative Services (DS) needs to know which classes are components, what services they might provide etc. Therefore your bundle should contain an XML file for DS which exactly defines this. You might know such XML configuration files from other frameworks – however, the DS format is rather simple and – the good part – you never have to write this by hand and never even have to look at it (ok, if things go wrong, it might sometimes help to check it). At runtime the SCR implementation will read these descriptor files and manage the components and services. Oh, I forgot to explain SCR 🙂 It stands for Service Component Runtime and can be seen as the container defined by DS. Now usually people use SCR and DS as synonyms though that is not quiet correct for the purists amongst us.

So let’s start…

Components

If you want to write a component which is managed by the container, just add the @Component annotation to your class:

package com.mycompany.cool.project.impl;

import org.osgi.service.component.annotations.Component;

@Component
public class MyFirstComponent { }

Build your project, deploy your bundle into an OSGi framework which has SCR running (I recommend the implementation from Apache Felix, version 2.0 or higher) – and your component will be instantiated by the container on bundle start. As a component has never public API but is a private implementation, the class should go into a private package which is not exported by the bundle! It is good style to add impl or similar somewhere in the package name, like com.mycompany.cool.project.impl.

Now, while this component runs and works – it’s not really useful as the component does nothing.

Lifecycle

As noted above, the container manages the lifecycle of the component, its instantiation and removal. In order to make this work, the component class needs the default zero argument constructor. However, if the component wants to do something during the creation or the deletion phase, it can implement an activate and/or deactivate method and mark it with the according annotation:

package com.mycompany.cool.project.impl;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Deactivate;
 
@Component
public class MyFirstComponent {
 
    @Activate
    protected void activate() {
        // do something
    }
 
    @Deactivate
    protected void deactivate() {
        // do something
    }
}

It is good practice to name these methods activate and deactivate – however you could pick any other name if you want. The methods have to be protected with no return value.

Still, we have a component not doing that much, so lets do something “more” usefull:

package com.mycompany.cool.project.impl;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
 
@Component
public class MyFirstComponent {
 
    private volatile boolean doRun;
 
    @Activate
    protected void activate() {
        final Thread t = new Thread() {
            public void run() {
                doIt();
            }
        };
        t.setDaemon(true);
        doRun = true;
        t.start();
    }
 
    private void doIt() {
        while (doRun) {
            System.out.println("I'm still alive!");
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {}
        }
    }
 
    @Deactivate
    protected void deactivate() {
        doRun = false;
    }
}

We create a new thread in activate and start it – in the thread we print out a message every minute. In addition we use a boolean variable to stop the thread when the component gets deactivated. While this example is not a production ready implementation, it shows that the thread of the activate and deactivate method “belong” to the component container – so the component should return as quickly as possible and do not block this method. Therefore we created an own thread. Please note, that this is just an example to demonstrate something, for things like timed execution, you would rather use a scheduler invoking your component periodically instead of running an own thread inside your component. The Apache Sling scheduler is a great way of doing things like these.

Using Services

A single component alone does usually not make up an application – it is rather assembled of dozens if not hundreds of components interacting. And interaction happens by using services.
So let’s extend our example – we use the event admin (another OSGi compendium spec with a great implementation from the Apache Felix project). The event admin is a service which allows us to send out events in a publish/subscrib kind of way. So each event gets a topic, and subscribers subscribe with the topics they are interested in.

A component can use other services by using the @Reference annotation. The container uses dependency injection and injects references into fields:

package com.mycompany.cool.project.impl;
 
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
 
@Component
public class MyFirstComponent {
 
    @Reference
    private EventAdmin eventAdmin;
 
    private volatile boolean doRun;
 
    @Activate
    protected void activate() {
        final Thread t = new Thread() {
            public void run() {
                doIt();
            }
        };
        t.setDaemon(true);
        doRun = true;
        t.start();
    }
 
    private void doIt() {
        while (doRun) {
            final Event event = new Event("alive", null);
            this.eventAdmin.sendEvent(event);
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {}
        }
    }
 
    @Deactivate
    protected void deactivate() {
        doRun = false;
    }
}

The above example looks pretty simple and from a developer’s point of view it is simple. You just declare an instance variable with the type of the service you want (services are registered by the interface(s) they implement) and add the @Reference annotation. Before the component is activated (the activate method is called), this instance field is set with the event admin service from the container. Therefore it is safe to assume that the event admin service is available and setup.

As OSGi is highly dynamic, bundles and services can come and go – so the event admin might be there or not, disappear, reappear etc. You don’t really have to care about this (at least not for the moment). Your component is only active if the event admin is available – if not, your component will either not be activated or will get deactivated. We’ll go deeper into references later on and learn how to cope with all the dynamics of services.

With just these four annotations you already know the building blocks for developing OSGi components and services. I suggest you test out the examples and make yourself familiar with using your favorite development environment. Once you are able to successfully build and deploy these components, you’re ready for the cool fun stuff of DS which I will show in part two.

Stay tuned.

Hello world!

It took some time, but my website has a undergone several changes – which hopefully enable me to blog about interesting stuff in the future. The past has not seen frequent updates from me, the main reason (excuse?) being very old software in my web space. I’ve now removed all that stuff and replaced it with something new…

Let’s see how this works

Apache Axis2 Book

I recently had the change to review the second edition of the Apache Axis2 book from Deepal Jayasinghe and Afkham Azeez. I think it gives a nice overview of the various web services aspects and how to develop applications with Apache Axis2. On the one hand it can be used as a reference for the various web services standards and Java APIs in this area, on the other hand it also covers important topics like clustering and enterprise integration patterns. It comes with samples which show how to use Axis2. In general its a nice book which you consider when using Axis2. Some examples or descriptions could be a little bit more detailed though.
There is still the Packt Graphic Apps and Libs Campaign.

Increasing Interest in JCR and Apache Sling

I’m attending some tech conferences in the Java space for several years now; for the last years I’m trying to push JCR, Apache Jackrabbit, and Apache Sling at various occasions – mostly through several talks. It seems to me that there is a change/increase in interest for these topics.
While two years ago, people have not been really that interested in JCR and usually asked questions along the line of “why should i use this? I have a database, it works fine” etc., this has definitly changed now. There are more and more people interested in alternatives to a POD (plain old database). It seems to me that the pain with traditional dbs is now too much and they’re searching for nosql solutions. Don’t get me wrong, JCR is not the golden hammer for data storage – there are valid use cases for PODs, but there are also many use cases where an alternative like JCR is much better suited.
Today people ask questions like “I looked at jcr, I have this problem, and I think I could do it this way. What do you think?” and of course variations on this theme.
I don’t think that this is motivated through the NOSQL hype, I ratherthink that this is a parallel movement which has the same origin. In addition, these people seems to know a lot about Apache Jackrabbit and usually ask deep going questions. As I’m not working on Jackrabbit itself – I’m a user of Jackrabbit – these questions usually give me a hard time 🙂
While I have a hard time with Jackrabbit questions, people seem often to have a hard time understanding the needs for Apache Sling. For one this might be cause they are still living in their POD driven world and know how to handle applications based on databases. Building applications on top of NOSQL solutions is a slightly different thing. When it comes to Apache Sling which is a web framework, it is immediately compared against web application frameworks with all the nice ui features, widget libraries and whatnot. And as Sling does not provide a UI library it is often immediately discarded.
But on the bright side as soon as people realize that they need something like JCR and now need a way to get all this content stored in the repository out to the users in a nice, elegant and flexible way, they also realize that Apache Sling helps a lot.
So my hope is that the adaption of JCR is increasing (and I think that is already the case) and that this drives the adoption of Apache Sling as well 🙂
And of course we are not day dreaming in Apache Sling – we will continue it’s development and add missing pieces or provide bridges etc.

Rapid Development with Apache Sling using an IDE

Apache Sling allows you to use scripts to render your content. Usually these scripts are stored in the repository as specific path. While it is possible to directly edit a script in the repository (using WebDAV), this editing happens out of your project’s context. But fortunately there is a better way!
Usually your project consists of modules (or a single module) which are deployed as OSGi bundles. To get your scripts into the repository, you add the scripts as resources to your project and use the initial content feature from Apache Sling to add the scripts to the repository.
So you usually end up with your module (bundle) checked out in your IDE (Eclipse for example), you do your initial development here (develop your OSGi services and scripts). For testing purposes you deploy the bundle (using the Maven Sling Plugin) which copies your scripts into the repository. From here they get picked up by Sling. If you now edit your scripts directly in the repository you have to take care to synchronize the changes with your checked out project in your IDE which can be an error prone and annoying task. Or you can edit the scripts in your IDE and then either redeploy your bundle or manually copy the scripts via WebDAV – which doesn’t make the process easier.
Fortunately Sling provides some tooling which makes these extra steps obsolete – actually we have this feature for a long time now but I always forgot to write about it…of course the following is only interesting for you, if you’re using Maven for your project.
Now, imagine your scripts are for your own node types which use the namespace prefix “myapp”, so you have a “src/main/resources/SLING-INF/content” (this is a convention for initial content) directory in your project. This content directory now contains a sub directory “libs” (or “apps” or any other configured search path) with your scripts. Underneath “libs” you have the “myapp” folder with a folder for each node type and this folder contains then your scripts (it’s really easier than it is to describe in textual form).
You’ll add a configuration for the Maven Bundle Plugin for adding the initial content header to your pom.xml:

<Sling-Initial-Content>
SLING-INF/content/libs/myapp;overwrite:=true;path:=/libs/myapp
</Sling-Initial-Content>

This basically copies the contents of the “/libs/myapp” folder on bundle install into the repository at the same location. On each update the contents gets overwritten.
Now add the Maven Sling Plugin to your pom.xml:

<plugin>
<groupId>org.apache.sling</groupId>
<artifactId>maven-sling-plugin</artifactId>
<version>2.0.3-incubator-SNAPSHOT</version>
<executions>
<execution>
<id>install-bundle</id>
<goals>
<goal>validate</goal>
<goal>install</goal>
</goals>
<configuration>
<mountByFS>true</mountByFS>
</configuration>
</execution>
</executions>
</plugin>

In the configuration above you can spot to new features of the latest plugin version: the validate goal will validate all *.json files and more important for our topic, the configuration “mountByFS” with the value “true”. Apache Sling has an extension bundle called file system provider (aka fsresource) which allows you to mount a file system path into the resource tree. So basically you can point for example the Sling resource path /myphotos to some directory on your server containing photos. This allows you to directly use files with Sling without copying them into the repository. Once you have installed this bundle into Sling and use the above configuration, each time you build your bundle with Maven and do a “mvn install”, the Maven Sling plugin will create a fsresource configuration for your initial content. In our case the Sling resource path “/libs/myapp” points to the file system directory “/src/main/resources/SLING-INF/content/libs/myapp”. So once you’ve done an initial install of your bundle, you can directly change the scripts in your IDE in your project. And the changes get immediately active, no need to sync and no need to copy. This makes development turnarounds for scripting much shorter as there is no turnaround any more.
The whole thing comes with a little drawback – with the configuration from above, your build fails if no Sling instance is reachable. So you should use a Maven profile for this configuration.

JAX, Apache Sling and Accidental Complexity

This year the number one Java conference in Germany, the JAX 09, is great as always. With nearly the same number of attendees it’s crowded in the positive sense – although you have to go to a session in time to get a good seat. I’ve seen a lot of highlights today – but first was my own presentation about JCR, OSGi, Scripting and REST – which presented the great Apache Sling web framework. Apache Sling uses Apache Felix as the OSGi framework and Apache Jackrabbit for the content repository. My session was very well attended, more than I expected, and while preparing the talk I noticed that I actually have more presentation material for JCR/Jackrabbit and OSGi/Felix than for Sling itself; although Sling is of course the topic of the session.
I think this shows that Sling is really a very clever framework, leveraging existing stuff and combining it in a productive way – this goes hand in hand with the great keynote tonight from Neal Ford – now, I can’t summarize it for you, but one of the key points was: don’t make things more complex than they should be (just because somethings that it makes sense or is cool). Look around and make use if available stuff – even if that doesn’t look cool for your developers. Most of the time is spent on accidental complexicy which in the end causes projects to fail.
I’m in the software world for over 20 years now and Neal is spot on with his message; i’ve seen a lot of projects fail because of this or because of one (or more) of the anti-patterns Neal mentioned.
Unfortunately I missed the sessions from Neal’s collegue Ted Neward which I enjoyed last year, but I saw an interesting session about the tools in Spring IDE for Spring, OSGi and Spring DM – now this looks pretty cool to me; I’m not in favour of using Spring as I think that there are more lightweight 🙂 solutions when it comes to OSGi – but on the other hand giving the fact that everyone and his dog knows Spring and given such good tooling with Spring IDE, it’s really hard to advocate something else. With the upcomming OSGi blueprint specification this will also have an impact on OSGi. And in the light of Neal’s talk, what could possible reasons be to not use this stuff? It would be great if the tooling would work with any OSGi framework and not just the Spring server.
But these are just excerpts from the day – and it’s just the first day; I’m looking forward to tomorrow when the OSGi day takes place!
During the breaks I’m trying to finish some stuff for the upcomming Sling release – we hope to get it out in the next weeks. So stay tuned.