OSGi ServiceFactory возвращает некастируемый объект

Я пытался сделать эту работу в течение всего дня, и это разочаровывает, потому что я не вижу ничего плохого в своем коде.

Вот мои занятия:

DisplayerServiceFactory.java

package com.lincesoft.imperator.displayer.provider;

import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;

import com.lincesoft.imperator.displayer.api.Displayer;

public class DisplayerServiceFactory implements ServiceFactory<Displayer> {

    public static final String NAME = "displayer_service_factory";

    @Override
    public void ungetService(Bundle bundle, ServiceRegistration<Displayer> registration, Displayer service) {
        // TODO Auto-generated method stub
    }
    @Override
    public Displayer getService(Bundle bundle, ServiceRegistration<Displayer> registration) {
        return new DisplayerImplementation();
    }
}

Это мой Activator.java для пакета, содержащего DisplayerServiceFactory

package com.lincesoft.imperator.displayer.launcher;

import java.util.Hashtable;

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

import com.lincesoft.imperator.displayer.api.Displayer;
import com.lincesoft.imperator.displayer.provider.DisplayerServiceFactory;

public class Activator implements BundleActivator {

    private ServiceRegistration<?> DisplayerFactoryRegistration;

    @Override
    public void start(BundleContext bundle_context) throws Exception {
        System.out.println("Starting the Displayer Provider Bundle");
        ServiceFactory<Displayer> displayer_service_factory = new DisplayerServiceFactory();
        Hashtable<String,String> properties = new Hashtable<String,String>();
        properties.put("service.vendor", DisplayerServiceFactory.NAME);
        DisplayerFactoryRegistration = bundle_context.registerService(Displayer.class.getName(), displayer_service_factory,properties);
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println("Stopping the Displayer Provider Bundle");
        DisplayerFactoryRegistration.unregister();
    }
}

и вот часть кода встроенного контейнера OSGI, который запускает пакет previus

/* Get a displayer instance from the service factory provided by the displayer provider bundle */
        ServiceReference<?>[] service_references = null;
        try {
            service_references = my_bundle_context.getServiceReferences(Displayer.class.getName(),"(service.vendor=displayer_service_factory)");
        } catch (InvalidSyntaxException e) {
            System.out.println("Sintaxis para obtener displayer_service_factory_reference invalida.");
            e.printStackTrace();
        }
        ServiceReference<?> displayer_service_factory_reference = null;
        if (service_references!=null && service_references.length==1) {
             displayer_service_factory_reference = service_references[0];
        } else {
            //Throw new NoDisplayerFactoryException();
        }
        Displayer bundle_displayer_instance = (Displayer) my_bundle_context.getService(displayer_service_factory_reference);

когда я запускаю этот код, это дает мне это исключение

Exception in thread "main" java.lang.ClassCastException: com.lincesoft.imperator.displayer.provider.DisplayerImplementation cannot be cast to com.lincesoft.imperator.displayer.api.Displayer
at com.lincesoft.imperator.procurator.launcher.Procurator.main(Procurator.java:94)

почему это происходит? Понятно, что DisplayerImplementation является экземпляром Displayer.

Также я выполнил некоторую отладку и в классе ServiceFactory (DisplayerImplementation instanceof Displayer) возвращает true, однако, когда я получаю реализацию displayer из ServiceFactory, зарегистрированной в качестве службы, (DisplayerImplementation instanceof Displayer) возвращает false.

это может быть ошибка в реализации фреймворка, который я использую? Я использую Феликс, кстати.

если вы попали сюда, спасибо за чтение! и я буду очень признателен, если вы попытаетесь мне помочь. Хорошего дня! или ночь!

2 ответа

Решение

У вас есть особый случай, когда вы хотите получить доступ к службе OSGi из-за пределов контейнера OSGi. Это можно сделать только с помощью пакета API снаружи контейнера, поскольку вы не можете получить доступ к пакетам из пакетов.

У вас уже есть пакет com.lincesoft.imperator.displayer.api в пути к классам за пределами контейнера. Поэтому вам просто нужно добавить этот пакет в свойство фреймворка org.osgi.framework.system.packages.extra. Таким образом, контейнер публикует пакет api внутри osgi.

Как писал Балаз, вы также должны убедиться, что у вас нет пакета api внутри одного из развертываемых вами пакетов. Это гарантирует, что OSGi не случайно выберет неправильный пакет API.

Я хочу задать еще один маленький вопрос, я действительно не хочу создавать другой вопрос просто для того, чтобы задать этот вопрос, и я не редактирую исходный вопрос, потому что тогда он может быть не обновлен, так что здесь все идет. невозможно получить доступ к пакету, который пакет выставляет в контейнере извне? поэтому приложение, которое выполняет встроенный контейнер, может использовать его, не добавляя его в путь к классам. из того, что я знаю, я не вижу способа сделать это, поэтому мне просто нужно будет экспортировать API из системного пакета и не развертывать его как пакет. но, возможно, вы, ребята, знаете способ! спасибо за чтение и извините его не уместно спросить это здесь.

Другие вопросы по тегам