Search code examples
javaosgikarafblueprint

Apache Karaf Blueprint Service <reference> is not injecting the objects


Karaf reference is not injecting the reference objects. Please see my setup and code.

Version: apache-karaf-3.0.5

Part 1: Service class

Service:

package org.jrb.test;

public interface MyService
{
    String echo(String message);
}

package org.jrb.test;

public class MyServiceImpl implements MyService
{
    public String echo(String message)
    {
        return "Echo processed: " + message;
    }
}

Blueprint:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">

    <bean id="serviceBean" class="org.jrb.test.MyServiceImpl"/>

    <service id="MyService" ref="serviceBean" interface="org.jrb.test.MyService"/>

</blueprint>

i can see my service in list:

onos> service:list | grep serviceBean

osgi.service.blueprint.compname = serviceBean

Part 2: consumer class for testing

Blueprint

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">

    <reference id="MyService" interface="org.jrb.test.MyService"/>

    <bean id="b" class="org.ct.command.AddCommand" activation="eager" >
        <property name="serviceBn" ref="MyService" />
    </bean>

    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
        <command>
            <action class="org.ct.command.AddCommand"/>
        </command>
    </command-bundle>

</blueprint>

In Java:

package org.ct.command;

import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;

import org.jrb.test.MyService;

@Command(scope = "onos", name = "service-add", description = "Adds a Client")
public class AddCommand implements Action
{
    private MyService serviceBn;

    public void setServiceBn(MyService serviceBn)
    {
        this.serviceBn = serviceBn;
    }

    public MyService getServiceBn()
    {
        return service;
    }

    @Override
    public Object execute(CommandSession session) throws Exception
    {
        System.out.println("Executing command add");

        if (serviceBn != null) {
            System.out.println("serviceBn is not null");
            System.out.println(serviceBn.echo("testing....."));
        } else {
            System.out.println("serviceBn is null !!");
        }
    }
}

In the above code, if i run the command "service-add", my serviceBn is always null. The reference is not injecting the bean.

Is there anything missing in my code?


Solution

  • Perhaps you could use a different approach. As you construct your AddCommand as a Blueprint bean you could provide the MyService object as a constructor parameter:

    @Command(scope = "onos", name = "service-add", description = "Adds a Client")
    public class AddCommand implements Action
    {
       private MyService serviceBn;
    
       public AddCommand(MyService myService) {
          this.serviceBn = myService;
       }
       ...
    }
    

    In Blueprint you then specify:

        ...
        <reference id="MyService" interface="org.jrb.test.MyService"/>
    
        <bean id="b" class="org.ct.command.AddCommand" activation="eager" >
           <argument ref="MyService" />
        </bean>
        ...
    

    In our project we prefer this approach to property injection.

    Update:

    With the current blueprint there are two instances created. The bean is instance seperatly created.

    To inject the service to the command you could try something like this:

    <reference id="MyService" interface="org.jrb.test.MyService" availability="mandatory" />
    
    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
      <command name="service:add">
         <action class="org.ct.command.AddCommand">
            <property name="serviceBn" ref="MyService"/>
         </action>
      </command>
    </command-bundle>