Sign in

E-mail *, (xx@domain.com)
Password *

Register | Forgot password

Blogs

Recent blogs

RSS - Blogs
March 9, 2010
State of OSGi in the Java world
March 4, 2010
Reach more people with Google Translate
March 3, 2010
Get My Advice
February 26, 2010
What? Where!?!
February 11, 2010
Split it!

All Blogs...


Accessing services in GX WebManager

March 5, 2009

As most of you will know the GX WebManager Component Framework is an application level abstraction build on top of the Apache Felix implementation of the OSGi specification. GX WebManager Components are basically services as are the platform services provided. Therefore building WebManager Components, that do a little more then just sitting there, means you are accessing other services. Here is a short overview of the different ways you can do that and why you should or should not prefer them.

Using Component Dependencies

In the Component Framework we explicitly added the concept of dependencies on other components or, for that matter, any service in general. So, at the risk at losing all my readers after this sections, here is the spoiler.. as a component developer you should (almost?) always prefer this option! By using Component Dependencies you stay within the development model, that keeps things simple to start with. In addition it provides you with many ease-of-development advantages hiding the complexity of dealing with services at the bare OSGi™ level.

The Component Framework allows you to declare which collaborators you either require or would like to use and brings them to you. This is commonly known as dependency injection, a form of Inversion of Control (IoC). This has some serious advantages:

  1. The Component Framework will inject your dependencies and optionally invoke your registered callbacks. This means that your do not have to deal with service location in your business logic.
  2. The Component Framework will actually deregister your Component when one or more of your required dependencies is not available. This means that you do not have to think about dealing with this scenarios in your business logic.

These obvious advantages allow you to keep your business logic clean and therefore readable and, maybe even more important, testable. How to use Component Dependencies and how they work is detailed in the developer documentation but here are a few snippets to give you an idea:

Registering a required dependency that is injected on the member field

//Component Activator
private ServiceComponentDefinitionImpl getServiceComponentDefinition() {
    // Adding a required dependecy without callbacks
    ComponentDependencyImpl cDep = new ComponentDependencyImpl();
    cDep.setServiceName(ServiceToTrack.class.getName());
    cDep.setRequired(true);
    definition.setDependencies(new ComponentDependency[]{ cDep });
    return definition;
 }
//Component Implementation 
private ServiceToTrack myInjectedService; // automagically injected when available

Registering an optional dependency that is passed on through a callback

//Component Activator
private ServiceComponentDefinitionImpl getServiceComponentDefinition() {
   // Adding an optional dependecy with callbacks for tracking
   ComponentDependencyImpl cDep = new ComponentDependencyImpl();
   cDep.setServiceName(ServiceToTrack.class.getName());
   cDep.setRequired(false);
   cDep.setAddedCallback("serviceToTrackAdded");
   cDep.setRemovedCallback("serviceToTrackRemoved");
   definition.setDependencies(new ComponentDependency[]{ cDep });
   return definition;
}
//Component Implementation
private static final Set myTrackedServiceSet = Collections
    .synchronizedSet(new HashSet());
public void serviceToTrackAdded(ServiceReference ref, Object obj) {
   ref.getBundle(); // OSGi classloading bug workaround
   myTrackedServiceSet.put((ServiceToTrack) obj);
}
public void serviceToTrackRemoved(ServiceReference ref, Object obj) {
   myTrackedServiceSet.remove((ServiceToTrack) obj);
}

Accessing services at the OSGi™ level

There is also the option of accessing services using the standard OSGi™ interfaces. Again, the Component Framework is merely an abstraction and we are not hiding anything. If you are implementing standard Component you are always extending ComponentBase that will allow you to access the OSGi™ BundleContext and you can use this as your starting point for accessing any service you may need. For example:

//Component Implementation
ServiceReference[] refs = getBundleContext().getServiceReferences(TrackedService.class.getName(), null);
for (ServiceReference ref : refs) {
   TrackedService ct = (TrackedService) getBundleContext().getService(ref);
   // Do something sensible...
}

Although there is nothing wrong with this code it should be clear that you lost the 'deregister if required dependency unavailable' feature, you are getting OSGi boilerplate in your business logic and thus your code becomes harder to test.

Accessing services through the Framework

Finally you could lookup services through the Framework service locator and, although it is also documented in our developer documentation for very specific use cases, I must stress that you actually should NEVER use it when implementing a Component. If you are tempted to use it, take a step back and look at your design. Having said that.. Using it would look something like this:

//Component Implementation
Object[] services = FrameworkFactory.getInstance().getFramework().getServices(TrackedService.class.getName(), null);

Using this pattern in your Component implementation is bad because it breaks the isolation that the Component/Service model provides. You are tying your implementation to a singleton outside your control. Actually, to be honest, you are tying it to a singleton that is even outside to OSGi container itself. All chances of properly ever testing your code have gone.

So why is it there? Well you could consider it to be an implementation detail of the Component Framework. As GX WebManager encapsulates the OSGi™ runtime in a standard web application we needed some way to bridge these two worlds and this was the obvious choice. Looking back we should have probably hidden it by not exposing it through the framework classloader but now there is no way back without breaking backward compatibility. Mea culpa :)

Closing statements

I hope this post has made this topic a little clearer. I recommend reading the developer documentation if you want to know more about using the Component Dependency feature. As always, do not hesitate to post your comments or get in touch with me if you have additional questions!

Next time I feel like writing a blog I will go into a little more detail on the topic of dependency injection.

Regards,

Bram


patricka | 05-03-2009 11:00

Bram, you evil person... Teaching us wrong methods!

How about marking that source with:

//Wrong! Use Component Dependencies instead!



That will save us - the copy/paste generation - from making mistakes later.
Great reading otherwise, kudos!

Greetings,

Patrick



Cthulhu | 09-03-2009 14:29

I've actually struggled to fully grasp WebManager's service injection / system, and I actually disagree with some of the design choices made therein (although I'm pretty sure that a lot of the choices were made because of the OSGI implementation you're using). In particular, I have / had problems with the following points:

* Defining a ComponentDependency is done by a string value, which is 'assumed' to be the name of a class, whilst that's only checked when the dependency is created. Changing the setServiceName()'s method signature to only accept Class objects (i.e. SomeClass.class) would increase typesafety and, at a compile-time level, prevent incorrect input. What would stop me from entering "Pietje Puk" as an input to the setServiceName, for example?

* The techniques used seem (to me) a bit of an odd combination of the Dependency Injection and Service Locator patterns. You define the dependencies that a Component has in the ComponentDefinition, and WebManager (or Felix?) 'injects' those into the Component object. That object, from then on, acts as a Service Locator for that component. However, the 'other' components in a WCB, such as the controller, but also a Servlet object, somehow have to get their hands onto the 'Service Locator' object. For the Controller, this isn't that big of a problem, since there's a 'getComponent()' method defined in its parent class that returns the component / service locator. However, such a method does not exist for, say, a Servlet, since it does not inherit from a WebManager class, but from Java's own HttpServlet class. So far, I've seen only two working solutions, neither of which are pretty (one being making the service locator / component a singleton, the other having the servlet assign itself statically to the service locator and have the service locator assign the services to the servlet when it's 'onStart()' method is called).

* The usual method of service injection is / seems to be through reflection, at least in the default archetypes, which means that a class's field is directly altered by some external party. In my (totalitarian) book, that's a Bad Thing, since firstly it makes the 'private' modifier completely obsolete, and second because it allows for no additional behaviour to be added in a setter object. Also, since the dependencies are only injected after the object itself is created, there's little that can be done to 'check' the object, i.e. make sure it has all services and whatnot assigned to itself. Okay, a component that doesn't get all the services will be removed from WebManager again, but still - this approach makes it pretty much impossible for a component to do anything while it's still 'under construction', i.e. when the constructor(s) for each class in a component are called.

I've grown quite fond of Spring's approach to dependency injection a year and a half ago during my previous internship. It allows full control over not just one part of a component (i.e. the Component class, service locator), but over all the components. If it were to be applied to WCB activation, it would allow, say, an Element component's Controller to get its required services, say, the Authorization service, right at construction-time, without it having to get a reference to a component who might not have its dependencies yet (due to the asynchronous nature of object creation and dependency injection in this particular case).

A lot of my grievances is / are ranting, and some of my arguments are probably based on ignorance or baseless assumption, but I do personally believe that Spring's approach to handling dependencies is 'better' in a wide number of ways. I've made a document / blogpost on this particular subject, which is probably outdated or incorrect by now based on the aforementioned reasonings, but it does, I think, have a core of truth into itself. I don't know if it would be possible to 'change' the current approach to dependency management (although I'd give it a go if I have the time for it), but it would certainly be worth looking into. See the post at http://greatjustice.info/gx-webmanagers-wcb-dependency-management/.



bramk | 19-03-2009 00:38

Hi Cthulhu,

thank you for your feedback. As you know bare OSGi basically provides a service locator mechanism and we provide a form of dependecy injection on top of that. Kind of like Spring DM, but still you make some valid points. Getting into detail is way out of scope of this reply box so I will get into detail and respond to your concerns in a next post soon.

regards,
Bram


 
pengtaoli | 28-04-2009 09:39

Where I could find the material about the OSGi design part?


About the Author

Return to all blogs


Bram de Kruijff is Product Architect and one of the co-architects of the GX WebManager framework with a focus on OSGi and services framework. Bram is part of the NAF Web 2.0 forum group to define standards on community technologies.

Read all Brams blog entries

Other blog entries:

June 26, 2009
Presentation at NAF Insight WEB 2.0
April 21, 2009
GX WebManager 9.8 on Java SE 6: The right stuff!
April 17, 2009
dOSGi talk at JSpring 2009
June 3, 2008
A few SDK tips & tricks
May 29, 2008
Maven secrets: Dynamic Maven properties with Beanshell
May 27, 2008
GX WebManager on SpringSource Application Platform
May 9, 2008
JavaOne 2008 wrapup
April 14, 2008
Maven secrets: assembling a WCB zip
April 11, 2008
ApacheCon EU 2008 impressions
April 4, 2008
OSGi techtalk at JTeam


Share:

del.icio.us
digg
Technorati
Slashdot
Reddit
YahooMyWeb
NewsVine
ekudos
© 2010 GX creative online development B.V.

Disclaimer

This website (GXdeveloperweb.com) may discuss or contain opinions, (sample) coding, software or other information that does not include GX official interfaces, instructions or guidelines and therefore is not supported by GX. Changes made based on this information are not supported.  GX will not be held liable for any damages caused by using or misusing the information, software, instructions, code or methods suggested on this website, and anyone using these methods does so at his/her own risk. GX offers no guarantees and assumes no responsibility or liability of any type with respect to the content of this website, including any liability resulting from incompatibility between the content of this website and the materials and services offered by GX. By using this website you will not hold, or seek to hold, GX responsible or liable with respect to the content of this website.