Expand my Community achievements bar.

SOLVED

Separate OSGI services api from implementation

Avatar

Former Community Member

It is considered best practice to create separate OSGi bundles for the API and implementation of a service. I use multi-module maven projects so the modules are arranged like this :-

parent |- all |- config |- content |- services |- taglib |- view

The 'services' module is where (up until now) I create the service class and its api typically under package names like :-

my.company.domain.aem.services.api  -  IHelloWorld.java (interface)

my.company.domain.aem.services        -  HelloWorld.java (implementation)

However, when you do that and use the maven-bundle-plugin BOTH of these classes will end up in the SAME bundle since thats the default behaviour (scans all src).

Whilst its easy to ensure that only the interface is EXPORTED, it really ought to be in its own bundle.

It *is* possible to change that behaviour and create 2 bundles using either a separate profile or separate <execution> configuration, but both of these are generally considered to be an anti-pattern.

The only other approach appears to be to create an additional module with it own POM and thus its own build output. So in addition to the above structure add a new module ;-

|- services-api (and move my.company.domain.aem.services.api  -  IHelloWorld.java (interface) into it)

That also means that you need to add a dependency in the 'services' module to 'services-api' module (also to taglib if it happens to use the service)

I can certainly get this approach to work, but I thought it was worth asking whether anyone else does this differently ?

Kind Regards

Fraser.

1 Accepted Solution

Avatar

Correct answer by
Employee

Hi Fraser,

You're correct that the appropriate solution is to create a single Maven project for each bundle. This is a general Maven best practice where each project has a single primary artifact. However, at that point, you shouldn't be using a Maven multimodule project, but rather independent projects. The only reason to have separate bundles for your API and implementation is if they are on different release cycles which means having independent Maven projects (possibly with a common parent, although the parent would be in its own project). In my experience, the extra effort of having different release cycles is rarely worth the effort for a single AEM project. It would be useful if you were working in a complex organization (perhaps this is what you mean by multi-disciplined teams) with multiple simultaneous AEM projects going on which dependend upon a common framework, at which point the framework would logically have a separate release cycle from the project cycles.

You're correct that the archetype choice doesn't really matter here -- neither the Adobe Multimodule Content Package archetype nor the CQ Blueprints archetype are designed for independent release cycles as they both generate mulitmodule projects. If you really want to go down that road, you can use the Adobe Simple Content Package Archetype along with the Sling JCR Install Archetype (http://sling.apache.org/documentation/development/maven-archetypes.html).

Regards,

Justin

View solution in original post

4 Replies

Avatar

Correct answer by
Employee

Hi Fraser,

You're correct that the appropriate solution is to create a single Maven project for each bundle. This is a general Maven best practice where each project has a single primary artifact. However, at that point, you shouldn't be using a Maven multimodule project, but rather independent projects. The only reason to have separate bundles for your API and implementation is if they are on different release cycles which means having independent Maven projects (possibly with a common parent, although the parent would be in its own project). In my experience, the extra effort of having different release cycles is rarely worth the effort for a single AEM project. It would be useful if you were working in a complex organization (perhaps this is what you mean by multi-disciplined teams) with multiple simultaneous AEM projects going on which dependend upon a common framework, at which point the framework would logically have a separate release cycle from the project cycles.

You're correct that the archetype choice doesn't really matter here -- neither the Adobe Multimodule Content Package archetype nor the CQ Blueprints archetype are designed for independent release cycles as they both generate mulitmodule projects. If you really want to go down that road, you can use the Adobe Simple Content Package Archetype along with the Sling JCR Install Archetype (http://sling.apache.org/documentation/development/maven-archetypes.html).

Regards,

Justin

Avatar

Level 10

When writing OSGi bundles for AEM, its recommended that you use Adobe Maven Archetype as described here:

http://dev.day.com/docs/en/cq/current/core/how_to/how_to_use_the_vlttool/vlt-mavenplugin.html

You can place your interfaces and implementation classes in separate packages if you choose to do so. 

Avatar

Former Community Member

Actually we are using the CQ Blueprints archetype which will produce the structure described above. We prefer this over the simpler Adobe one since it provides finer grained modules which we find more useful especially for multi-disciplined teams. You can find information about it here :-

http://www.cqblueprints.com/setup/maven.html

I doubt the choice of archetype is the issue here ?

Can you show me an example from your POM using the Adobe archetype that will create a separate bundle for the service interface and another separate bundle for the service implementation ?

Fraser.

Avatar

Former Community Member

justin_at_adobe wrote...

Hi Fraser,

You're correct that the appropriate solution is to create a single Maven project for each bundle. This is a general Maven best practice where each project has a single primary artifact. However, at that point, you shouldn't be using a Maven multimodule project, but rather independent projects. The only reason to have separate bundles for your API and implementation is if they are on different release cycles which means having independent Maven projects (possibly with a common parent, although the parent would be in its own project). In my experience, the extra effort of having different release cycles is rarely worth the effort for a single AEM project. It would be useful if you were working in a complex organization (perhaps this is what you mean by multi-disciplined teams) with multiple simultaneous AEM projects going on which dependend upon a common framework, at which point the framework would logically have a separate release cycle from the project cycles.

You're correct that the archetype choice doesn't really matter here -- neither the Adobe Multimodule Content Package archetype nor the CQ Blueprints archetype are designed for independent release cycles as they both generate mulitmodule projects. If you really want to go down that road, you can use the Adobe Simple Content Package Archetype along with the Sling JCR Install Archetype (http://sling.apache.org/documentation/development/maven-archetypes.html).

Regards,

Justin

 

Hey Justin,

thanks for your response. I think I have also reached the same conclusion. My reasoning is as follows. If I was writing a service where I was expecting a number of implementations of the same interface, then I would definitely separate out the API into its own bundle. However all of the services I have written for AEM thus far have a single purpose and context and it that sense both the API and implementation are coherent to package together within a single bundle. As you say, this doesn't really seem to warrant the complexity of separate bundles since it doesn't really add significant value. There is an interesting debate around dispensing with the interface entirely and just exposing the implementation itself (some schools of thought suggest that unless an interface has more than 1 implementation it has little value as an abstraction). Personally I think thats a step too far and still advocate creating and exporting the API only since this provides other benefits, such as hiding parts of the implementation which should remain internal / private.

Thanks for the clarification around archetypes.

Kind Regards

Fraser