Запуск проектов OSGI Bundle

Я работаю над Eclipse IDE и пытаюсь запустить проекты пакетов osgi. Я создал 2 пакета, используя проекты плагинов.

  1. CalculatorService (который действует как издатель)
  2. CalculatorClient (который действует как подписчик)

Это моя структура проекта

структура проекта

Когда я пытаюсь запустить CalculatorService, он работает нормально, и служба активна. Затем, когда CalculatorService становится ACTIVE, я запускаю CalculatorClient. Но он остается в статусе RESOLVED, а не ACTIVE.

Статус службы

Несмотря на то, что мне не удалось получить пакет CalculatorClient Bundle ACTIVE, я попытался запустить эту службу и получил исключение gogo следующим образом.

исключение gogo

Поскольку это исключение говорит о том, что с моим start() методом пакета CalculatorClient что-то не так, я приложил его к настоящему документу.

package calculatorclient;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import calculatorservice.ICalculatorService;

public class CalculatorClient implements BundleActivator {

    ServiceReference servRef;
    private static BundleContext context;

    static BundleContext getContext() {
        return context;
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext bundleContext) throws Exception {
        CalculatorClient.context = bundleContext;
        System.out.println("Start calculate client service");
        servRef = context.getServiceReference(ICalculatorService.class.getName());
        ICalculatorService calc = (ICalculatorService)context.getService(servRef);

        //Print
        System.out.println("Enter Operator");
        BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
        String oper = br1.readLine();
        BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
        double no1 = Double.parseDouble(br2.readLine());
        BufferedReader br3 = new BufferedReader(new InputStreamReader(System.in));
        double no2 = Double.parseDouble(br3.readLine());

        System.out.print("Answer is ");
        calc.calculateService(oper, no1, no2);

    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext bundleContext) throws Exception {
        CalculatorClient.context = null;
        System.out.println("Good Bye !!!");
        context.ungetService(servRef);
    }

}

Класс-активатор пакета CalculatorService

package calculatorservice;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

public class CalculatorActivator implements BundleActivator {

    ServiceRegistration servReg;
    private static BundleContext context;

    static BundleContext getContext() {
        return context;
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext bundleContext) throws Exception {
        CalculatorActivator.context = bundleContext;
        ICalculatorService calc = new CalculatorServiceImpl();
        servReg = context.registerService(ICalculatorService.class.getName(), calc, null);
    }

    /*
     * (non-Javadoc)
     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext bundleContext) throws Exception {
        CalculatorActivator.context = null;
        servReg.unregister();
    }

}

MANIFEST.MF службы калькулятора

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: CalculatorService
Bundle-SymbolicName: CalculatorService
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: calculatorservice.CalculatorActivator
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.osgi.framework;version="1.3.0"
Bundle-ActivationPolicy: lazy
Export-Package: calculatorservice

Клиент калькулятора MANIFEST.MF

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: CalculatorClient
Bundle-SymbolicName: CalculatorClient
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: calculatorclient.CalculatorClient
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: calculatorservice, org.osgi.framework;version="1.3.0"
Bundle-ActivationPolicy: lazy

Трассировка стека

!STACK 0
org.osgi.framework.BundleException: Could not resolve module: org.sonatype.m2e.mavenarchiver [1674]
  Unresolved requirement: Require-Bundle: org.eclipse.m2e.jdt; bundle-version="[1.0.0,2.0.0)"
    -> Bundle-SymbolicName: org.eclipse.m2e.jdt; bundle-version="1.6.2.20150902-0002"; singleton:="true"
       org.eclipse.m2e.jdt [1376]
         Unresolved requirement: Require-Bundle: org.eclipse.m2e.core; bundle-version="[1.6.0,1.7.0)"
           -> Bundle-SymbolicName: org.eclipse.m2e.core; bundle-version="1.6.2.20150902-0002"; singleton:="true"
              org.eclipse.m2e.core [1371]
                Unresolved requirement: Require-Bundle: org.eclipse.m2e.workspace.cli; bundle-version="0.1.0"

    at org.eclipse.osgi.container.Module.start(Module.java:434)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1562)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)
    at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
    at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)

Любые предложения о том, почему я не могу перевести этот пакет CalculatorClient из состояния RESOLVED в состояние ACTIVE, будут высоко оценены.


person Nayantara Jeyaraj    schedule 02.08.2017    source источник
comment
Если вы используете Equinox, загляните в папку конфигурации вашего контейнера OSGi. Equinox помещает сообщения об ошибках в некоторые файлы с уникальными именами в папке конфигурации, если не указано иное. Поскольку вы не можете знать, в каком порядке запускаются ваши пакеты, вам никогда не следует использовать context.getService() в методе запуска активатора, поскольку другой пакет может быть еще не запущен.   -  person Balazs Zsoldos    schedule 02.08.2017
comment
@BalazsZoldos . В моем проекте я сначала запускаю пакет CalculatorService, щелкнув правой кнопкой мыши MANIFEST.MF этого пакета, а затем выбрав Run as -> OSGI Framework. И как только CalculatorService bundle is ACTIVE` я делаю то же самое на MANIFEST.MF пакета CalculatorClient. Таким образом, в этом случае пакет не будет запускаться индивидуально в том же порядке, в котором я их запускаю, независимо от `context.getService()?   -  person Nayantara Jeyaraj    schedule 02.08.2017
comment
Что ж, где-то в вашем методе запуска есть исключение, но я не знаю, куда записывается его трассировка стека. Поэтому я могу только предложить уродливое решение, заключающееся в том, что вы должны обернуть все тело метода start с помощью try-catch и вызвать e.printstacktrace в catch. По крайней мере, вы увидите настоящее исключение.   -  person Balazs Zsoldos    schedule 02.08.2017
comment
@BalazsZsoldos Я распечатал трассировку стека и добавил к своему вопросу. Не могли бы вы предложить что-то на основе этого. Я новичок в связках osgi.   -  person Nayantara Jeyaraj    schedule 02.08.2017
comment
Я вряд ли думаю, что это трассировка стека, которая выходит из вашего метода запуска. Это исключение, но оно не зависит от вашей текущей проблемы. При вызове функции Double.parseDouble может возникнуть исключение NumberFormatException. Это мое первое предположение, но было бы лучше увидеть исключение с трассировкой стека, а не гадать. Обратите внимание, что в реальных системах вы не должны блокировать метод запуска пакета (например, ожидание какого-либо пользовательского ввода), так как это блокирует запуск всего компьютера.   -  person Balazs Zsoldos    schedule 02.08.2017


Ответы (1)


Я внес несколько незначительных изменений в оба моих класса Activator.

  • Вместо использования экземпляра контекста пакета, объявленного в методах start() и stop(), я использовал параметр объекта контекста пакета в методах start() и stop().

  • Добавьте аннотацию @Override прямо перед методами start() и stop().

  • Добавьте аннотацию @Override прямо перед объявлением метода в классе, который реализует интерфейс в пакете издателя.

  • Удалите все ненужные объявления по умолчанию, созданные во время инициализации проекта, из классов Activator.

Класс активатора издателя

package calculatorservice;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

public class CalculatorActivator implements BundleActivator {

    ServiceRegistration serviceRegistration;

    @Override
    public void start(BundleContext bundleContext) throws Exception {
        ICalculatorService iCalculatorService = new CalculatorServiceImpl();
        serviceRegistration = bundleContext.registerService(ICalculatorService.class.getName(), iCalculatorService, null);
    }

    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        serviceRegistration.unregister();
    }

}

Класс реализации издателя

package calculatorservice;

public class CalculatorServiceImpl implements ICalculatorService{
    @Override
    public void calculateService(String operator, double no1, double no2){
        String PLUS = "+";
        String MINUS = "-";
        String MUL = "*";
        String DIV = "/";
        if(PLUS.equals(operator))
        {
            System.out.print((no1+no2));
        }
        else if (MINUS.equals(operator)){
            System.out.println((no1-no2));
        }
        else if (MUL.equals(operator)){
            System.out.print((no1*no2));
        }
        else if(DIV.equals(operator)){
            if(no2 == 0.0){
                System.out.print(" \"Divide by zeo error \" ");
            }
            else{
                System.out.print((no1/no2));
            }
        }
        else if (operator == ""){
            System.out.print(" \"Enter value for operator\" ");
        }
        else{
            System.out.print(" \"Enter one of the operators +_*/ \" ");
        }
    }
}

Класс активатора клиента

package calculatorclient;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import calculatorservice.ICalculatorService;

public class CalculatorClient implements BundleActivator {

    ServiceReference serviceReference;

    @Override
    public void start(BundleContext bundleContext) throws Exception {
        System.out.println("Start calculate client Service");
        serviceReference = bundleContext.getServiceReference(ICalculatorService.class.getName());
        ICalculatorService iCalculatorService = (ICalculatorService)bundleContext.getService(serviceReference);

        System.out.println("Enter operator");
        BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
        String operator = br1.readLine();

        System.out.println("Enter no1 = ");
        BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
        double no1 = Double.parseDouble(br2.readLine());

        System.out.println("Enter no2 = ");
        BufferedReader br3 = new BufferedReader(new InputStreamReader(System.in));
        double no2 = Double.parseDouble(br3.readLine());

        iCalculatorService.calculateService(operator,no1,no2);
    }

    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        System.out.println("Good Bye!!!");
        bundleContext.ungetService(serviceReference);       
    }

}

И тогда я запустил Издательскую MANIFEST.MF отдельно. Как только это было ACTIVE, я запустил MANIFEST.MF клиента. После того, как оба они были ACTIVE, запустите службу клиента, и программа будет работать нормально.

person Nayantara Jeyaraj    schedule 03.08.2017