About a week ago I posted on how to create an OSGi bundle for Apache Sling. In the comments section of that post Sling developer Bertrand Delacretaz mentioned that the Maven build tool might save some work in that respect. Inspired by that comment I would like to show in this post how to convert the example to a Maven build.
If you have not done so start off by downloading and installing Maven and get familiar with the basic concepts, especially the pom.xml file where the build is configured.
A big advantage of using Maven for building OSGi bundles for Sling is that the descriptor files serviceComponents.xml and MANIFEST.MF are automatically generated from Java annotations in the source files. Therefore, it is not necessary anymore to explicitly write any descriptor files when Maven is used. Instead, a number of annotations need to be added to the HelloServiceImpl class:
...
/** HelloService implementation
*
* @scr.service
*
* @scr.component
* immediate="true"
* metatype="false"
*
* @scr.property
* name="service.description"
* value="A sample from Day"
*
* @scr.property
* name="service.vendor"
* value="Day"
*
*/
public class HelloServiceImpl implements
HelloService{
/** @scr.reference */
private SlingRepository repository;
...
Maven will process the @scr. annotations. For example, the @scr.property annotations get converted into scr:property elements in serviceComponents.xml.
The @scr.reference annotation is even more useful. Not only does it generate the corresponding element in serviceComponents.xml but it also generates the bind/unbind methods for the injection of the repository object. As a consequence these two methods can be removed from the source code of HelloServiceImpl.
The rest of the configuration is done in the pom.xml file, especially the bits we need to get the correct MANIFEST.MF. Have a look at the attched pom.xml and consider the the lines
<configuration>
<instructions>
<Export-Package>
!com.day.samples.impl,
com.day.samples.*
</Export-Package>
<Private-Package>
com.day.samples.*
</Private-Package>
</instructions>
</configuration>
This configuration will be picked up by Maven. It will write into MANIFEST.MF:
Export-Package: com.day.samples;uses:="javax.jcr"
All imports the bundle needs do not have to be configured explicitly, but are generated automatically into MANIFEST.MF. Nice!
Another useful feature is auto-deployment of the produced bundle into Sling. This is configured in pom.xml in the lines:
<configuration> <slingUrl> http://localhost:8080/system/console/install </slingUrl> <user>admin</user> <password>admin</password> </configuration>
Make sure to adapt your port and password accordingly. For CRX Quickstart the port is likely to be 7402.
In order to enable Maven to find some additional (Maven) repositories that contain the Apache Snapshot two additional sections are necessary in pom.xml. See the parts repositories and pluginRepositories of that file.
As usual, all sources discussed in this post are attached. Download the jar, unpack it and execute
mvn install
This will compile and deploy the bundle into Sling without further manual work.


1) you don't know at a glance what services you're registering
2) what if one service depends on another in the same bundle? if serviceComponents.xml loads each service in order, then one could put the dependent service after the service it depends on. but through annotations, this doesn't seem possible
The @scr.service spec is clear, by default all interfaces implemented by the component are made available, and you can restrict to specific interfaces by listing them.
A service depending on another in the same bundle is not a problem, and neither is the order of service declarations. Services are started dynamically and asynchronously by Service Components Runtime (SRC), as needed to satisfy the dependencies, so you have no control on their starting order anyway.
#2 makes sense. by that extension, there's no way at all to guarantee a service being available? can a reasonable assumption be made that all properly made services will startup correctly at some point if their chain of dependencies also startup correctly?
About bundle activators, they don't replace serviceComponents.xml but they are needed when the standard SCR startup/initialization semantics are not sufficient. The Sling bundles/extensions/threaddump bundle, for example, uses an Activator as it needs to register a custom UncaughtExceptionHandler, and sets up some Apache Felix extensions.
[1] https://issues.apache.org/jira/browse/SLING-490