2016-04-29 3 views
1

Я играю с компонентами OSGi DS и ConfigurationAdmin.OSGi изменить метод события не называется

Я создал простой настраиваемый компонент

@Component(service=ConfigurableService.class) 
public class ConfigurableService { 

    private String message; 

    @Activate 
    public void activate(Map<String, Object> params) { 
    System.out.println("Activate configurable"); 
    message = (String) params.get("msg"); 
    } 

    @Modified 
    public void modified(Map<String, Object> params) { 
    System.out.println("Modify configurable"); 
    message = (String) params.get("msg"); 
    } 

    @Deactivate 
    public void deactivate(Map<String, Object> params) { 
    System.out.println("Deactivate configurable"); 
    message = (String) params.get("msg"); 
    } 

    public void execute() { 
    System.out.println("Service says: " + message); 
    } 
} 

Затем я создал компонент командной оболочки Felix Gogo, чтобы вызвать конфигурацию с помощью ConfigurationAdmin

@Component(property = { 
    CommandProcessor.COMMAND_SCOPE + "=fipro", 
    CommandProcessor.COMMAND_FUNCTION + "=configure" 
}, 
service = ConfigurationCommand.class 
) 
public class ConfigurationCommand { 

    private ConfigurationAdmin cm; 

    @Reference(unbind="-") 
    public void setConfigAdmin(ConfigurationAdmin cm) { 
    this.cm = cm; 
    } 

    public void configure(String input) throws IOException { 
    Configuration config = cm.getConfiguration("org.fipro.osgi.config.ConfigurableService"); 
    Hashtable<String, Object> props = new Hashtable<>(); 
    props.put("msg", input); 
    config.update(props); 
    } 
} 

И, наконец, я создал еще один компонент командной оболочки Felix Gogo который использует ConfigurableService

@Component(property = { 
    CommandProcessor.COMMAND_SCOPE + "=fipro", 
    CommandProcessor.COMMAND_FUNCTION + "=welcome" 
}, 
service = WelcomeCommand.class 
) 
public class WelcomeCommand { 

    private ConfigurableService service; 

    @Reference(unbind="-") 
    public void setConfigurable(ConfigurableService service) { 
    this.service = service; 
    } 

    public void updatedConfigurable(ConfigurableService service, Map<String, Object> properties) { 
    System.out.println("ConfigurableService updated"); 
    } 

    public void welcome() { 
    service.execute(); 
    } 
} 

Если я запустил приложение OSGi с пакетами, которые содержат эти компоненты, я ожидаю, что при выполнении welcome изначально я увижу, что компонент активирован, а выход службы равен нулю, поскольку пока не применяется никакая конфигурация (это верно для последовательных звонки). Если я потом выполнил configure Dirk, я ожидаю, что метод, аннотированный с помощью @Modified, будет выполнен, чтобы указать, что настройка сервиса обновлена. Я также ожидаю, что метод updatedConfigurable в WelcomeCommand выполнен. По крайней мере, это мое понимание от чтения спецификации.

Теперь я наблюдаю различное поведение в Equinox и Felix.

Равноденствие:

Модифицированный метод называют как ожидалось, и ConfigurableService настроена правильно. Но updatedConfigurable(<Service>, <Map>) не вызывается. Только если я изменю подпись метода, чтобы принять ServiceReference, вызывается обновленный метод.

спецификация говорит, что все эталонные методы событий поддерживают следующие сигнатуры методы

void <method-name>(ServiceReference); 
void <method-name>(<parameter-type>); 
void <method-name>(<parameter-type>, Map); 

Есть исключение для обновленного метода я не видел в спецификации или это проблема в Equinox, где я должен поднять билет?

Felix:

Если я запускаю тот же самый пример на Феликса в Bndtools, ни модифицирована, ни методы обновления дозвонились. Я проверил ConfigurationCommand и доступен ConfigurationAdmin, поэтому при обновлении конфигурации нет никаких исключений. Но он никогда не применяется так или иначе.

Я что-то упустил при запуске примера на Феликсе?

Update:

Добавление консольных выходов каждого метода Жизненный цикл событий создает следующий вывод:

____________________________ 
Welcome to Apache Felix Gogo 

g! ConfigurationCommand: Activate 
ConfigurableService: Activate 
WelcomeCommand: Activate 
welcome 
Service says: null 
g! configure Dirk 
g! welcome 
Service says: null 
g! exit 0 
WelcomeCommand: Deactivate 
ConfigurableService: Deactivate 
ConfigurationCommand: Deactivate 

Как вы можете видеть, модифицируют и обновленные события, никогда не называется.

ответ

2

Я думаю, что проблема заключается в жизненном цикле для команд Гого.

Gogo не поддерживает служебные объекты, пока команда не запущена. Он отслеживает ServiceReference, но не вызывает getService, пока вы на самом деле не вызовете команду welcome. Поэтому, когда вы вызываете welcome, будет создан экземпляр WelcomeCommand, что в свою очередь создает экземпляр ConfigurableService.

Позже, когда команда welcome завершается, WelcomeCommand освобождается, поэтому оба WelcomeCommand и ConfigurableService будет GC'd. Поэтому ни один экземпляр ConfigurableService не живет достаточно долго, чтобы получить событие Modified.

Чтобы решить эту проблему, попробуйте сделать WelcomeCommandнемедленного:

@Component(immediate = true, ...) 

UPDATE

При дальнейшем обсуждении с Dirk по электронной почте, то получается, что вопрос место связывания. В Config Admin конфигурации по умолчанию «привязаны» к пакету, который их создает, в этом случае пакет, содержащий ConfigurationCommand. После привязки они не могут быть использованы другой связкой, поэтому ConfigurableService никогда не видит конфигурацию.

Чтобы создать несвязанную конфигурацию, которая может быть использована любым пакетом, вызовите версию с двумя аргументами ConfigAdmin.getConfiguration() и передайте null для второго аргумента.

+0

Нет, это не решит проблему на Феликсе. –

+0

Можете ли вы проверить (используя команды 'scr: list' и' scr: info'), что ConfigurableService фактически является живым, а экземпляр существует. Также, пожалуйста, избавитесь от материала 'unbind =" - "', это не нужно, и я не знаю, какие побочные эффекты он может иметь. –

+0

Я удалил атрибут 'unbind =" - "'. Я просто добавил это, потому что спецификация говорит, что необходимо явно сказать, что нет никакого метода отвязывания. В противном случае новая поддержка аннотации DS в Neon жалуется. Для Феликса я перешел к Bndtools, и нет проблемы с отсутствующим методом unbind. Тем не менее это ничего не меняет. используя 'scr: list' и' scr: info', показывается, что 'ConfigurableService' активен (' State: active'). Для меня все выглядит хорошо. Есть ли что-то особенное, что я должен искать? –

Смежные вопросы