DZone Forums
Go Back   DZone Forums > Community > Languages & Frameworks > Java
Reload this Page problem with OSGi Declarative Services factory component
Notices
Reply
 
LinkBack Thread Tools Display Modes
  (#1 (permalink)) Old
Member
 
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: May 2008
Default problem with OSGi Declarative Services factory component - 06-04-2008, 05:08 AM

Hi, all. I'm trying to do some OSGi app using Declarative Services. I faced a problem. I tried to describe it as simple as I could, but it still turned out a big one. Please spend a minute to understand it. I really need help 'cause there is very few examples avaliable in the net. Thanks in advance.
So here is my problem. I have an interface:

public interface Greeter {
public void setName(String text);
public void greet();
}

And I have a class that implements it:

public class BaseGreeter implements Greeter {
String name = null;
public void setName(String text) {
name = text;
}
public void greet() {
System.out.println("Hello, " + name);
}
public void activate() {
greet();
}
}

Next I have two classes that extends this base class:

public class MorningGreeter extends BaseGreeter {
public void greet() {
System.out.println("Good morning, " + name);
}
}
public class AfternoonGreeter extends BaseGreeter {
public void greet() {
System.out.println("Good afternoon, " + name);
}
}

In this example everything is simple - all the difference between the classes is in one word. In reality I want to build some "black boxes" - classes that implement the same interface but provide cardinally different functionality.
So, the main idea is as follows. I want some other people to write some other Greeters (black boxes). These people should know nothing about OSGi - they just write a class that extends BaseGreeter and override the greet() method.
My main program does the following: it reads some xml-config file that looks something like this:

<config>
<greeter class="org.example.MorningGreeter" name="Ann"/>
<greeter class="org.example.MorningGreeter" name="Sue"/>
<greeter class="org.example.AfternoonGreeter" name="Ann"/>
<greeter class="org.example.AfternoonGreeter" name="John"/>
</config>

It gets the ConfigurationAdmin Service:
ConfigurationAdmin ca = ...
And then for every <greeter> entry it posts a new Configuration:

Configuration conf = ca.createFactoryConfiguration("example.greeterfactory");
Hashtable d = ... // construct a dictionary that contains two entries: "greeter.class" (= "class" atribute of <greeter>) and "greeter.name" (= "name" attribute of <greeter>)
conf.update(d);

My OSGI-INF directory contains the following files:
  • basegreeter.xml

    <component name="basegreeter" factory="example.greeterfactory">
    <implementation class="org.example.BaseGreeter"/>
    <service>
    <provide interface="org.example.Greeter"/>
    </service>
    </component>
  • greeterfactory.xml

    <component name="example.greeterfactory">
    <implementation class="org.example.GreeterFactory"/>
    <service>
    <provide interface="org.osgi.service.component.ComponentFactory"/>
    </service>
    </component>
The GreeterFactory class is here:

public class GreeterFactory implements ComponentFactory {
public ComponentInstance newInstance(Dictionary properties) {
// here I take "greeter.class" property from properties and use the ClassLoader.getSystemClassLoader().loadClass(class ID) to load and construct the appropriate class: Greeter g = new ...
g.setName((String)properties.get("greeter.name"));
return null; // the first problem - how do I Construct ComponentInstance?
}
}

So the lifecycle as I see it must be as follows:
  1. Main program posts a new Configuration
  2. Some OSGi service (I can't be sure how it is called, it's all mixed up in my head) activates calls the factory newInstance method with given Dictionary
  3. The factory constructs a Greeter with the given properties and returns it to OSGi service
  4. OSGi service activates the component (which causes a simple hello sentence to appear)
Now what really happens. Here is what "services" command shows:
Code:
{org.osgi.service.component.ComponentFactory}={component.factory=example.greeterfactory, component.name=basegreeter, service.id=28}
  Registered by bundle: initial@reference:file:../workspace/org.example/ [4]
  No bundles using service.
{org.osgi.service.component.ComponentFactory}={greeter.class=org.example.MorningGreeter, service.pid=example.greeterfactory-1212569841845-0, service.factoryPid=example.greeterfactory, component.name=example.greeterfactory, component.id=1, greeter.name=Ann, service.id=29}
  Registered by bundle: initial@reference:file:../workspace/org.example/ [4]
  No bundles using service.
We see that the factory is present (service.id=28). Next should be the greeter: it has all the properties it needs BUT it is not a Greeter - it is another GreeterFactory. I checked whether it is because I return null from newInstance and found out that newInstance is never called. I understand that I mixed something up, but can't figure out what it is
Thanks for reading this up to the end anyway. And if you could help me or if you know anyone who can - I would be very-very grateful. Thank you
Reply With Quote
  (#2 (permalink)) Old
Member
 
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Jun 2008
Default You don't get to create the ComponentFactory - 06-04-2008, 07:08 PM

Quote:
Originally Posted by AlexandreSH View Post
greeterfactory.xml

<component name="example.greeterfactory">
<implementation class="org.example.GreeterFactory"/>
<service>
<provide interface="org.osgi.service.component.ComponentFactory"/>
</service>
</component>


The GreeterFactory class is here:

public class GreeterFactory implements ComponentFactory {
public ComponentInstance newInstance(Dictionary properties) {
// here I take "greeter.class" property from properties and use the ClassLoader.getSystemClassLoader().loadClass(class ID) to load and construct the appropriate class: Greeter g = new ...
g.setName((String)properties.get("greeter.name"));
return null; // the first problem - how do I Construct ComponentInstance?
}
}

In DS, when you declare a factory component (with the factory attribute), you are telling DS to register a ComponentFactory service on your behalf. DS provides the ComponentFactory object. Not you. When someone calls newInstance on the ComponentFactory object, a new instance of the declared implementation class (BaseGreeter) in this case will be declared.

It sounds like you are trying to do cannot be done using inheritance like you are trying. You will need to use a delegation model such that BaseGreeter will inspect its component properties for the desired specific class, construct an instance of that class and delegate the greet method to that instance.
Reply With Quote
  (#3 (permalink)) Old
Member
 
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: May 2008
Default 06-05-2008, 12:32 PM

Thank you, bjhargrave. In fact I found another solution myself. I guess it was because I set and wrote everything about the problem thoroughly. The answer came to me in about 5 hours after my post =) But thanks anyway. I'll think of your idea.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Where is the Component Palette? DavidGriffiths Eclipse 0 01-08-2009 01:30 AM
A Conceptual Problem with OSGi AlexandreSH Java 0 10-30-2008 06:23 AM
Declarative Toolbar Action Pouletchu Eclipse 0 08-03-2008 06:08 AM
Problem using Declarative Services u722 Java 0 07-02-2008 04:02 PM
Access OSGi servicees outside OSGi environment simongdkelly Eclipse 3 02-29-2008 09:43 AM


Copyright 1997-2009, DZone, Inc.
vBulletin Skin developed by: vBStyles.com