Невозможно динамически связать службы в Osgi Blueprint

Я новичок в OSGI Blueprint и столкнулся со странной проблемой.

У меня есть 2 отдельные базы данных: oracle и h2 (для тестирования) db

Контейнер чертежа выглядит примерно так:

<service ref='oracleDataSource' interface='javax.sql.DataSource'>
    <service-properties>
        <entry key='osgi.jndi.service.name' value='someJndiDatasourceName'/>
    </service-properties>
</service>

<bean id='oracleDataSource'
      class="CustomDataSourceImpl">
    <property name="connectionFactoryClassName" value="${datasource.type}"/>
    <property name="url" value="${url}"/>
    <property name="user" value="${username}"/>
    <property name="password" value="${password}"/>
    <property name="validateConnectionOnBorrow" value="true"/>
</bean>

Ясно, что приведенный выше сервис привязывается к oracleDataSource. Свойство datasource.type заполняется из файла конфигурации и имеет значение oracle.jdbc.pool.OracleDataSource.

Теперь мой вариант использования заключается в том, что если я хочу позже отредактировать файл конфигурации и изменить значение datasource.type на тип h2, то мой service-ref должен быть привязан к bean-компоненту, упомянутому ниже:

<bean id="h2ds" class="org.h2.jdbcx.JdbcDataSource">
    <property name="URL" value="${url}"/>
    <property name="user" value="${username}"/>
    <property name="password" value="${password}"/>
</bean>

Можем ли мы сделать такую ​​​​динамическую привязку в плане?

В принципе, я ищу что-то похожее на сервис-локатор.


person Sandy    schedule 13.12.2017    source источник
comment
Вы показали только элемент <service>, где вы предоставляете службу DataSource, но не показали элемент <reference>, где вы используете эту службу (которая обычно была бы из другого пакета). Пожалуйста, покажите это, потому что это находится на <reference>, где вы будете различать потенциально несколько служб-кандидатов DataSource.   -  person Neil Bartlett    schedule 14.12.2017
comment
Да, я пользуюсь услугой из другого пакета. Элемент ‹reference› для ‹service› <reference id="entityManagerFactory" interface="javax.persistence.EntityManagerFactory" filter="(osgi.unit.name=my-persistent-unit-name)" availability="mandatory"/> Но я считаю, что требование несколько отличается, мне нужно внедрить источник данных H2 в мой ‹service›< /b> всякий раз, когда я запускаю интеграционный тест pax. Для всего остального, кроме теста интеграции pax, я бы хотел, чтобы он привязывал источник данных оракула к моей ‹службе›.   -  person Sandy    schedule 14.12.2017
comment
Почему? Элемент <service> предназначен для того, чтобы взять фиксированный bean-компонент из пакета и экспортировать его как услугу. Это не сам боб, в который вы вводите. В своих интеграционных тестах вы просто используете пакет, который предоставляет DataSource с использованием H2 вместо Oracle.   -  person Neil Bartlett    schedule 14.12.2017


Ответы (1)


Элемент <service> в Blueprint не является bean-компонентом, в который вы внедряете. Его единственная цель — взять фиксированный bean-компонент из того же контейнера Blueprint (то есть пакета OSGi) и экспортировать его как сервис с некоторыми свойствами.

Правильное место для введения желаемой гибкости — это элемент <reference> в другом пакете, то есть точка, где вы потребляете услугу.

Таким образом, у вас может быть два пакета, предоставляющих услугу javax.sql.DataSource. Один реализован с помощью Oracle, другой реализован с помощью H2. В сценарии интеграционного тестирования вы используете пакет реализации H2 и опускаете пакет реализации Oracle. В производственной среде это наоборот.

ОБНОВЛЕНИЕ для уточнения:

Элемент <reference> в потребительском комплекте на самом деле не нужно менять... гибкость, о которой я упоминал выше, уже существует. Вот ссылка, которая у вас сейчас где-то есть (предположительно, вы на самом деле не указали):

<reference id="dataSourceService"
    interface="javax.sql.DataSource"/>

Это привязывается к любой службе типа DataSource, независимо от реализации, стоящей за ней. Если вы развернете только пакет Oracle, ваш потребитель получит источник данных Oracle. Если вы развернете только пакет H2, ваш потребитель получит источник данных H2. Потребителя не нужно менять, в чем прелесть OSGi Services.

person Neil Bartlett    schedule 14.12.2017
comment
Спасибо, Нил, за ценные комментарии. Я понимаю, откуда вы пришли, но я чувствую, что это недостаток дизайна, и его нужно будет согласовать позже, поскольку изменение повлияет на все другие пакеты, которые в настоящее время зависят от этого пакета. С учетом сказанного, не считаете ли вы хорошей идеей добавить еще один элемент ‹service› в существующий файл blueprint.xml. Например, <service ref=''h2ds" interface='javax.sql.DataSource'> <service-properties> <entry key='osgi.jndi.service.name' value='someJndiDatasourceName'/> </service-properties> </service> - person Sandy; 14.12.2017
comment
Почему это ошибка дизайна и почему это может повлиять на другие пакеты? На самом деле никакого влияния не будет. Они просто привязываются к службе DataSource и не должны интересоваться предоставляемым пакетом. - person Neil Bartlett; 15.12.2017
comment
Что касается вашего второго вопроса, нет, это не было бы хорошей идеей. При использовании отдельных пакетов поставщиков Oracle и H2 каждый пакет может зависеть только от используемого им драйвера JDBC. Вы предлагаете иметь один пакет, который знает, как подключиться как к Oracle, так и к H2. Это плохой модульный дизайн. - person Neil Bartlett; 15.12.2017
comment
Огромнейшее спасибо за ваш совет. Моя структура каталогов выглядит так: мой-проект содержит следующие a)common-bundle(contains the persistence.xml) b)oracle-bundle(sole purpose is to export oracle packages) c)integration-tests-bundle(contains datasource cfg file which has h2 and oracle db related properties viz driver,url,password,etc d)h2-bundle(exports h2 related packages and I've added this h2-bundle as a module within the integration-tests-bundle) e)client-bundle(where currently the datasource service is being consumed) - person Sandy; 15.12.2017
comment
Поскольку я новичок в этой среде OSGI, не могли бы вы сообщить мне, как мне изменить элемент ‹reference›, чтобы я мог ссылаться на реализацию h2 и опускать реализацию Oracle при выполнении интеграционного теста. В настоящее время ссылочный элемент выглядит так: <reference id="entityManagerFactory" interface="javax.persistence.EntityManagerFactory" filter="(osgi.unit.name=my-persistent-unit-name)" availability="mandatory"/> - person Sandy; 15.12.2017
comment
Элемент <reference> изменять не нужно. Это моя точка зрения. Вы привязываетесь к службе типа javax.sql.DataSource, но вам не нужно заботиться о том, какая реализация стоит за ней. - person Neil Bartlett; 15.12.2017
comment
Спасибо, Нил. Кажется, это идеальный подход. Я постараюсь реализовать так, как вы предложили, и скоро вернусь. - person Sandy; 16.12.2017