2015-07-04 5 views
0

Я пытался сделать эту работу целый день, и это отвратительно, потому что я не вижу ничего плохого в моем коде.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, который запускает пучок предков

/* 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.

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

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

+0

Я предполагаю, что интерфейс Displayer существует дважды. Если вы используете встроенный контейнер OSGi, я думаю, что интерфейс Displayer существует в одном из пакетов и в пути к классам приложения. Поэтому в комплекте используется интерфейс Displayer из другого пакета, в то время как приложение использует интерфейс Displayer из своего собственного пути к классам. Убедитесь, что интерфейс Displayer поступает только из пути к классам приложения, а не из любого пакета! –

+0

Чтобы получить точную информацию о том, откуда появились интерфейсы Displayer, поместите следующую строку внутри той части, где вы используете услугу, и где вы предлагаете эту услугу: System.out.println (Displayer.class.getClassLoader()); –

+0

в случае, если вы не читали, спасибо за ответ! ты был прав! –

ответ

1

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

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

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

+0

Вы были правы, господа! @ balazs-zsoldos теперь работает, и я понимаю, почему он не работал раньше. Спасибо! –

0

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

+0

К сожалению, это действительно невозможно. Если вы думаете о том, как работает классная загрузка, это довольно ясно. Классный загрузчик вне OSGi определяется банками на пути к классу. Поскольку пакеты OSGi не находятся в пути к классам, их пакеты/классы невидимы для внешнего загрузчика классов. –