0

I'm new to OSGI Blueprint and facing a strange issue.

I have 2 separate Databases: oracle and h2(to be used for testing) db

The blueprint container looks something like this:

<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>

Clearly, the service above binds to oracleDataSource . The datasource.type property gets populated from a configuration file and has a value of oracle.jdbc.pool.OracleDataSource

Now, my use-case is that suppose if I want to edit the configuration file later and change the value of datasource.type to h2 type, then my service-ref should bind to the bean mentioned below:

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

Can we do such kind of dynamic binding in blueprint?

Basically, I'm looking for something similar to service locator.

Sandy
  • 459
  • 2
  • 6
  • 19
  • You have only shown the `` element where you provide the DataSource service, but you haven't shown the `` element where you consume that service (which would normally be from another bundle). Please show that, because it is on the `` where you would discriminate between the potentially multiple candidate DataSource services. – Neil Bartlett Dec 14 '17 at 10:09
  • Yes,I'm consuming the service from a different bundle. The **** element for the **** `` But I believe the requirement is somewhat different,I need to inject the H2 Datasource to my **** whenever I run the pax integration test. For everything else,other than pax integration test,I'd like it to bind the oracle data source to my **** – Sandy Dec 14 '17 at 15:35
  • Why? The `` element is meant to take a fixed bean from within the bundle and export that as a service. It's not a bean itself that you are injecting into. In your integration tests you just use a bundle that provides `DataSource` using H2 instead of Oracle. – Neil Bartlett Dec 14 '17 at 15:52

1 Answers1

1

The <service> element in Blueprint is not a bean that you are injecting into. It's sole purpose is to take a fixed bean from within the same Blueprint Container (i.e. OSGi bundle) and export it as a service, with some properties.

The correct place for you to introduce the flexibility you want is in the <reference> element in another bundle, i.e. the point where you consume the service.

So you can have two bundles providing the javax.sql.DataSource service. One is implemented with Oracle, the other is implemented with H2. In an integration testing scenario you use the H2 implementation bundle and omit the Oracle implementation bundle. In production, it's vice versa.

UPDATE for clarification:

The <reference> element in the consumer bundle does not actually need to change... the flexibility I mentioned above already exists. Here is the reference you currently have somewhere (infererred, you have not actually specified):

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

This binds to any service of type DataSource, irrespective of the implementation behind it. If you deploy only the Oracle bundle then your consumer will get the Oracle Data Source. If you deploy only the H2 bundle then your consumer will get the H2 Data Source. The consumer does not need to be changed, which is the beauty of OSGi Services.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77
  • Thanks Neil for you precious comments. I understand where you're coming from, but I feel it's a design flaw and has to be agreed upon later as a change would impact all the other bundles which presently depends on this bundle. With that being said, do you think it's a good idea to introduce one more **** element within the existing blueprint.xml file. For Example, ` ` – Sandy Dec 14 '17 at 19:12
  • Why is this is a design flaw and why would there be any impact on other bundles? There would in fact be zero impact. They just bind to a `DataSource` service and should have no interest in the providing bundle. – Neil Bartlett Dec 14 '17 at 21:47
  • As to your second question, no it would not be a good idea. With separate Oracle and H2 provider bundles, each bundle can depend upon just the JDBC driver that it uses. You're proposing that you have one bundle which knows how to connect to both Oracle and H2. That is poor modular design. – Neil Bartlett Dec 14 '17 at 21:49
  • Immense thanks for your advice. My directory structure looks like this: my-project contains the following `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)` – Sandy Dec 15 '17 at 09:14
  • Since I'm very new to this OSGI environment, could you please let me know how should I modify the element so that I can refer to the h2 implementation and omit the Oracle one while executing Integration Test. Presently the reference element looks like this: `` – Sandy Dec 15 '17 at 09:19
  • 1
    The `` element does not need to be modified. That is my point. You bind to a service of type `javax.sql.DataSource` but don't need to care what the implementation behind it is. – Neil Bartlett Dec 15 '17 at 09:20
  • Thanks Neil.That seems to be an ideal approach. I’ll try to implement the way u suggested and will revert soon. – Sandy Dec 16 '17 at 20:54