Сервисная ссылка в OSGi / blueprint не работает должным образом - PullRequest
4 голосов
/ 17 марта 2011

В настоящее время у меня есть два пакета OSGi (bundle1 и bundle2), оба из которых предоставляют сервисы через план в EBA. В bundle2 blueprint.xml я хочу сослаться на сервис из bundle1 и Вставить в BuildService (код ниже), так как BuildService будет использоваться для вызова TicketService. Это, однако, приводит к исключению тайм-аута (также ниже). Похоже, что BuildService никогда не регистрируется в OSGi. Как бы я сделал что-то вроде этой работы?

blueprint.xml для bundle1:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:bptx="http://aries.apache.org/xmlns/transactions/v1.0.0">

    <bean id="TicketServiceBean" class="com.example.b2.impl.TicketServiceImpl">
        <bptx:transaction value="Required" method="*" />
    </bean>

        <service ranking="0" id="TicketService" interface="com.example.b2.service.TicketService" ref="TicketServiceBean">
        <service-properties>
            <entry key="service.exported.interfaces" value="*" />
        </service-properties>
    </service>  

</blueprint>

blueprint.xml для bundle2

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

    <bean 
        id="BuildServiceImplBean"
        class="com.example.b1.impl.BuildServiceImpl" 
        activation="eager" >
        <property name="ticketService" ref="TicketServiceRef" />
    </bean>  


    <service    
        id="BuildService" 
        ref="BuildServiceImplBean"
        interface="com.example.b1.service.BuildService"
        activation="eager"> 

        <service-properties>
            <entry key="service.exported.interfaces" value="*" />
        </service-properties>

    </service>



    <reference 
        id="TicketServiceRef" 
        interface="com.example.b2.service.TicketService" 
        availability="mandatory"
        activation="eager" />


</blueprint>

Реализация BuildService:

public class BuildServiceImpl implements BuildService {

    private TicketService ticketService;

    @Override
    public TicketBuildResponse ticketBuild(TicketBuildRequest ticketBuildRequest) throws BuildServiceException {

        //do stuff here
    }



    public TicketService getTicketService() {
        return ticketService;
    }

    public void setTicketService(TicketService ticketService) {
        this.ticketService = ticketService;
    }


}

При запуске сервера приложений (Websphere) я получаю следующее исключение:

  BlueprintCont E org.apache.aries.blueprint.container.BlueprintContainerImpl$1 run Unable to start blueprint container for bundle com.example.b1.module due to unresolved dependencies [(objectClass=com.example.b2.service.TicketService)]
                                     java.util.concurrent.TimeoutException
        at org.apache.aries.blueprint.container.BlueprintContainerImpl$1.run(BlueprintContainerImpl.java:273)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:453)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:315)
        at java.util.concurrent.FutureTask.run(FutureTask.java:150)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:207)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:736)

1 Ответ

5 голосов
/ 18 марта 2011

Вот решение: среда выполнения приложений OSGi обрабатывает удаленные сервисы иначе, чем локальные, из-за различий в семантике вызова по умолчанию (локальная передача по ссылке или удаленная передача по значению). Чтобы приложение случайно не вызвало экспортированную службу, которая предназначена только для вызовов по значению, оно скрыто от локальных поисков.

Решение этой проблемы состоит в том, чтобы экспортировать один и тот же компонент дважды, один раз для удаленных вызовов, а второй для локальных. Другими словами, вы бы добавили еще один элемент <service /> с той же конфигурацией, но без свойства service.exported.interfaces.

<service ranking="0" id="TicketServiceExport" interface="com.example.b2.service.TicketService" ref="TicketServiceBean">
    <service-properties>
        <entry key="service.exported.interfaces" value="*" />
    </service-properties>
</service>  

<service ranking="0" id="TicketService" interface="com.example.b2.service.TicketService" ref="TicketServiceBean"/>

На самом деле в веб-сфере также есть консоль osgi, которую можно найти в [local websphere installation]/profiles/[profileName]/bin/osgiApplicationConsole.bat. После запуска help() выдает список команд. Чтобы просмотреть импортированные сервисы из SCA, вы сначала подключаетесь к своему приложению (например, connect(2), где номер приложения указан в результатах команды list()). Затем вы можете сделать services("(service.imported=true)"), чтобы увидеть сервисные прокси, которые были добавлены SCA. Команда services() выведет список всех служб в приложении.

...